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" 11651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "clang/ARCMigrate/ARCMT.h" 1230660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/ARCMigrate/ARCMTActions.h" 1355fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/AST/ASTConsumer.h" 14471c8b49982d1132f30b0b0da27fef94fd6e4f67Benjamin Kramer#include "clang/AST/ASTContext.h" 15651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "clang/AST/Attr.h" 1630660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/AST/NSAPI.h" 17a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis#include "clang/AST/ParentMap.h" 1855fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/AST/RecursiveASTVisitor.h" 19651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "clang/Analysis/DomainSpecific/CocoaConventions.h" 2055fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Basic/FileManager.h" 2130660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/Edit/Commit.h" 2255fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Edit/EditedSource.h" 2330660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/Edit/EditsReceiver.h" 2455fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Edit/Rewriters.h" 2555fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Frontend/CompilerInstance.h" 2655fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Frontend/MultiplexConsumer.h" 2737ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis#include "clang/Lex/PPConditionalDirectiveRecord.h" 2855fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Lex/Preprocessor.h" 2955fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Rewrite/Core/Rewriter.h" 30269cca13cdafab34073158476de0391d1839ecd3Fariborz Jahanian#include "clang/StaticAnalyzer/Checkers/ObjCRetainCount.h" 3130660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "llvm/ADT/SmallString.h" 32176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines#include "llvm/ADT/StringSet.h" 332c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis#include "llvm/Support/Path.h" 34651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "llvm/Support/SourceMgr.h" 35651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "llvm/Support/YAMLParser.h" 3630660a898545416f0fea2d717f16f75640001e38Ted Kremenek 3730660a898545416f0fea2d717f16f75640001e38Ted Kremenekusing namespace clang; 3830660a898545416f0fea2d717f16f75640001e38Ted Kremenekusing namespace arcmt; 39269cca13cdafab34073158476de0391d1839ecd3Fariborz Jahanianusing namespace ento::objc_retain; 4030660a898545416f0fea2d717f16f75640001e38Ted Kremenek 4130660a898545416f0fea2d717f16f75640001e38Ted Kremeneknamespace { 4230660a898545416f0fea2d717f16f75640001e38Ted Kremenek 4330660a898545416f0fea2d717f16f75640001e38Ted Kremenekclass ObjCMigrateASTConsumer : public ASTConsumer { 44a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian enum CF_BRIDGING_KIND { 45a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian CF_BRIDGING_NONE, 46a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian CF_BRIDGING_ENABLE, 47a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian CF_BRIDGING_MAY_INCLUDE 48a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian }; 49a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian 5030660a898545416f0fea2d717f16f75640001e38Ted Kremenek void migrateDecl(Decl *D); 5158878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar void migrateObjCContainerDecl(ASTContext &Ctx, ObjCContainerDecl *D); 527556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian void migrateProtocolConformance(ASTContext &Ctx, 537556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian const ObjCImplementationDecl *ImpDecl); 54b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian void CacheObjCNSIntegerTypedefed(const TypedefDecl *TypedefDcl); 55d2dab64a438b7b8d57f8a10883e107d2bc0988edFariborz Jahanian bool migrateNSEnumDecl(ASTContext &Ctx, const EnumDecl *EnumDcl, 56bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian const TypedefDecl *TypedefDcl); 57b8941a15b6b5477a81c189614d0129070ac099f1Fariborz Jahanian void migrateAllMethodInstaceType(ASTContext &Ctx, ObjCContainerDecl *CDecl); 5826cf046ff3a2d24ff3e2c3757599976b644a06daFariborz Jahanian void migrateMethodInstanceType(ASTContext &Ctx, ObjCContainerDecl *CDecl, 5926cf046ff3a2d24ff3e2c3757599976b644a06daFariborz Jahanian ObjCMethodDecl *OM); 609c4759149c80464ca26dcc90c756f439e6640684Fariborz Jahanian bool migrateProperty(ASTContext &Ctx, ObjCContainerDecl *D, ObjCMethodDecl *OM); 618a6ad2a21dcb654db25cf66408466d2e7a93e09cFariborz Jahanian void migrateNsReturnsInnerPointer(ASTContext &Ctx, ObjCMethodDecl *OM); 62f85f5e4769730e06590d969ad3cbff879d8006f6Fariborz Jahanian void migratePropertyNsReturnsInnerPointer(ASTContext &Ctx, ObjCPropertyDecl *P); 63f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian void migrateFactoryMethod(ASTContext &Ctx, ObjCContainerDecl *CDecl, 648d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian ObjCMethodDecl *OM, 658d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian ObjCInstanceTypeFamily OIT_Family = OIT_None); 6646f4fd5938b0ff4ebbb83ba1df225f73d640613dFariborz Jahanian 67d76941102f17d5f4e88ef027151c20c95b745c8bFariborz Jahanian void migrateCFAnnotation(ASTContext &Ctx, const Decl *Decl); 68a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian void AddCFAnnotations(ASTContext &Ctx, const CallEffects &CE, 69c1cc488c3cf9ce7f7b7e211e891e2be7391e0e5aFariborz Jahanian const FunctionDecl *FuncDecl, bool ResultAnnotated); 70a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian void AddCFAnnotations(ASTContext &Ctx, const CallEffects &CE, 71c1cc488c3cf9ce7f7b7e211e891e2be7391e0e5aFariborz Jahanian const ObjCMethodDecl *MethodDecl, bool ResultAnnotated); 7257c372a674beee5054a57026de46c280df1df577Fariborz Jahanian 73dead50d347e9517d80f007a93df6295f66aa0f00Fariborz Jahanian void AnnotateImplicitBridging(ASTContext &Ctx); 74dead50d347e9517d80f007a93df6295f66aa0f00Fariborz Jahanian 75a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian CF_BRIDGING_KIND migrateAddFunctionAnnotation(ASTContext &Ctx, 76a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian const FunctionDecl *FuncDecl); 7746f4fd5938b0ff4ebbb83ba1df225f73d640613dFariborz Jahanian 78d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian void migrateARCSafeAnnotation(ASTContext &Ctx, ObjCContainerDecl *CDecl); 79d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian 805f7ac67c84e7b9a04fa4c5065e384f928c8f812fFariborz Jahanian void migrateAddMethodAnnotation(ASTContext &Ctx, 815f7ac67c84e7b9a04fa4c5065e384f928c8f812fFariborz Jahanian const ObjCMethodDecl *MethodDecl); 82651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 83651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void inferDesignatedInitializers(ASTContext &Ctx, 84651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const ObjCImplementationDecl *ImplD); 85176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 86176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines bool InsertFoundation(ASTContext &Ctx, SourceLocation Loc); 87651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 8830660a898545416f0fea2d717f16f75640001e38Ted Kremenekpublic: 8930660a898545416f0fea2d717f16f75640001e38Ted Kremenek std::string MigrateDir; 9074fd551c0ba344d62aedc8636ed81b45652f04d8Fariborz Jahanian unsigned ASTMigrateActions; 91e909a720149ba5025209096fb9ed17e0162c8873Argyrios Kyrtzidis FileID FileId; 92b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian const TypedefDecl *NSIntegerTypedefed; 93b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian const TypedefDecl *NSUIntegerTypedefed; 94651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::unique_ptr<NSAPI> NSAPIObj; 95651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::unique_ptr<edit::EditedSource> Editor; 9630660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileRemapper &Remapper; 9730660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileManager &FileMgr; 9837ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis const PPConditionalDirectiveRecord *PPRec; 99baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian Preprocessor &PP; 10030660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool IsOutputFile; 101176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines bool FoundationIncluded; 1027556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ObjCProtocolDecls; 103d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian llvm::SmallVector<const Decl *, 8> CFFunctionIBCandidates; 104176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines llvm::StringSet<> WhiteListFilenames; 105176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 10630660a898545416f0fea2d717f16f75640001e38Ted Kremenek ObjCMigrateASTConsumer(StringRef migrateDir, 10774fd551c0ba344d62aedc8636ed81b45652f04d8Fariborz Jahanian unsigned astMigrateActions, 10830660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileRemapper &remapper, 10930660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileManager &fileMgr, 11037ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis const PPConditionalDirectiveRecord *PPRec, 111baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian Preprocessor &PP, 1122c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis bool isOutputFile, 1132c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis ArrayRef<std::string> WhiteList) 11430660a898545416f0fea2d717f16f75640001e38Ted Kremenek : MigrateDir(migrateDir), 11574fd551c0ba344d62aedc8636ed81b45652f04d8Fariborz Jahanian ASTMigrateActions(astMigrateActions), 1166bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines NSIntegerTypedefed(nullptr), NSUIntegerTypedefed(nullptr), 117b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian Remapper(remapper), FileMgr(fileMgr), PPRec(PPRec), PP(PP), 118176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines IsOutputFile(isOutputFile), 119176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines FoundationIncluded(false){ 1202c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis 121176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines // FIXME: StringSet should have insert(iter, iter) to use here. 122176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines for (const std::string &Val : WhiteList) 123176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines WhiteListFilenames.insert(Val); 1242c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis } 12530660a898545416f0fea2d717f16f75640001e38Ted Kremenek 12630660a898545416f0fea2d717f16f75640001e38Ted Kremenekprotected: 127651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void Initialize(ASTContext &Context) override { 12830660a898545416f0fea2d717f16f75640001e38Ted Kremenek NSAPIObj.reset(new NSAPI(Context)); 12930660a898545416f0fea2d717f16f75640001e38Ted Kremenek Editor.reset(new edit::EditedSource(Context.getSourceManager(), 1304e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie Context.getLangOpts(), 1316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines PPRec)); 13230660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 13330660a898545416f0fea2d717f16f75640001e38Ted Kremenek 134651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool HandleTopLevelDecl(DeclGroupRef DG) override { 13530660a898545416f0fea2d717f16f75640001e38Ted Kremenek for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) 13630660a898545416f0fea2d717f16f75640001e38Ted Kremenek migrateDecl(*I); 13730660a898545416f0fea2d717f16f75640001e38Ted Kremenek return true; 13830660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 139651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void HandleInterestingDecl(DeclGroupRef DG) override { 14030660a898545416f0fea2d717f16f75640001e38Ted Kremenek // Ignore decls from the PCH. 14130660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 142651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) override { 14330660a898545416f0fea2d717f16f75640001e38Ted Kremenek ObjCMigrateASTConsumer::HandleTopLevelDecl(DG); 14430660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 14530660a898545416f0fea2d717f16f75640001e38Ted Kremenek 146651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void HandleTranslationUnit(ASTContext &Ctx) override; 1472c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis 1482c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis bool canModifyFile(StringRef Path) { 1492c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis if (WhiteListFilenames.empty()) 1502c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis return true; 1512c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis return WhiteListFilenames.find(llvm::sys::path::filename(Path)) 1522c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis != WhiteListFilenames.end(); 1532c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis } 154651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool canModifyFile(const FileEntry *FE) { 155651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!FE) 156651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return false; 157651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return canModifyFile(FE->getName()); 158651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 159651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool canModifyFile(FileID FID) { 160651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (FID.isInvalid()) 161651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return false; 162651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return canModifyFile(PP.getSourceManager().getFileEntryForID(FID)); 163651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 164651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 165651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool canModify(const Decl *D) { 166651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!D) 167651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return false; 168651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (const ObjCCategoryImplDecl *CatImpl = dyn_cast<ObjCCategoryImplDecl>(D)) 169651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return canModify(CatImpl->getCategoryDecl()); 170651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (const ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) 171651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return canModify(Impl->getClassInterface()); 172651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) 173651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return canModify(cast<Decl>(MD->getDeclContext())); 174651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 175651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FileID FID = PP.getSourceManager().getFileID(D->getLocation()); 176651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return canModifyFile(FID); 177651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 17830660a898545416f0fea2d717f16f75640001e38Ted Kremenek}; 17930660a898545416f0fea2d717f16f75640001e38Ted Kremenek 1804967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar} // end anonymous namespace 18130660a898545416f0fea2d717f16f75640001e38Ted Kremenek 1824967a710c84587c654b56c828382219c3937dacbPirama Arumuga NainarObjCMigrateAction::ObjCMigrateAction( 1834967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar std::unique_ptr<FrontendAction> WrappedAction, 18474fd551c0ba344d62aedc8636ed81b45652f04d8Fariborz Jahanian StringRef migrateDir, 18574fd551c0ba344d62aedc8636ed81b45652f04d8Fariborz Jahanian unsigned migrateAction) 1864967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar : WrapperFrontendAction(std::move(WrappedAction)), MigrateDir(migrateDir), 18774fd551c0ba344d62aedc8636ed81b45652f04d8Fariborz Jahanian ObjCMigAction(migrateAction), 1886bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines CompInst(nullptr) { 18930660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (MigrateDir.empty()) 19030660a898545416f0fea2d717f16f75640001e38Ted Kremenek MigrateDir = "."; // user current directory if none is given. 19130660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 19230660a898545416f0fea2d717f16f75640001e38Ted Kremenek 193176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesstd::unique_ptr<ASTConsumer> 194176edba5311f6eff0cad2631449885ddf4fbc9eaStephen HinesObjCMigrateAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { 19537ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis PPConditionalDirectiveRecord * 19637ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis PPRec = new PPConditionalDirectiveRecord(CompInst->getSourceManager()); 197176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines CI.getPreprocessor().addPPCallbacks(std::unique_ptr<PPCallbacks>(PPRec)); 198176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines std::vector<std::unique_ptr<ASTConsumer>> Consumers; 199176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Consumers.push_back(WrapperFrontendAction::CreateASTConsumer(CI, InFile)); 200176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Consumers.push_back(llvm::make_unique<ObjCMigrateASTConsumer>( 201176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines MigrateDir, ObjCMigAction, Remapper, CompInst->getFileManager(), PPRec, 202176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines CompInst->getPreprocessor(), false, None)); 203176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return llvm::make_unique<MultiplexConsumer>(std::move(Consumers)); 20430660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 20530660a898545416f0fea2d717f16f75640001e38Ted Kremenek 20630660a898545416f0fea2d717f16f75640001e38Ted Kremenekbool ObjCMigrateAction::BeginInvocation(CompilerInstance &CI) { 20730660a898545416f0fea2d717f16f75640001e38Ted Kremenek Remapper.initFromDisk(MigrateDir, CI.getDiagnostics(), 20830660a898545416f0fea2d717f16f75640001e38Ted Kremenek /*ignoreIfFilesChanges=*/true); 20930660a898545416f0fea2d717f16f75640001e38Ted Kremenek CompInst = &CI; 21030660a898545416f0fea2d717f16f75640001e38Ted Kremenek CI.getDiagnostics().setIgnoreAllWarnings(true); 21130660a898545416f0fea2d717f16f75640001e38Ted Kremenek return true; 21230660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 21330660a898545416f0fea2d717f16f75640001e38Ted Kremenek 21430660a898545416f0fea2d717f16f75640001e38Ted Kremeneknamespace { 215176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines // FIXME. This duplicates one in RewriteObjCFoundationAPI.cpp 216176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines bool subscriptOperatorNeedsParens(const Expr *FullExpr) { 217176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines const Expr* Expr = FullExpr->IgnoreImpCasts(); 21887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return !(isa<ArraySubscriptExpr>(Expr) || isa<CallExpr>(Expr) || 21987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar isa<DeclRefExpr>(Expr) || isa<CXXNamedCastExpr>(Expr) || 22087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar isa<CXXConstructExpr>(Expr) || isa<CXXThisExpr>(Expr) || 22187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar isa<CXXTypeidExpr>(Expr) || 22287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar isa<CXXUnresolvedConstructExpr>(Expr) || 22387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar isa<ObjCMessageExpr>(Expr) || isa<ObjCPropertyRefExpr>(Expr) || 22487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar isa<ObjCProtocolExpr>(Expr) || isa<MemberExpr>(Expr) || 22587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar isa<ObjCIvarRefExpr>(Expr) || isa<ParenExpr>(FullExpr) || 22687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar isa<ParenListExpr>(Expr) || isa<SizeOfPackExpr>(Expr)); 227176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 228176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 229176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines /// \brief - Rewrite message expression for Objective-C setter and getters into 230176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines /// property-dot syntax. 231176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines bool rewriteToPropertyDotSyntax(const ObjCMessageExpr *Msg, 232176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Preprocessor &PP, 233176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines const NSAPI &NS, edit::Commit &commit, 234176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines const ParentMap *PMap) { 235176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (!Msg || Msg->isImplicit() || 2360e2c34f92f00628d48968dfea096d36381f494cbStephen Hines (Msg->getReceiverKind() != ObjCMessageExpr::Instance && 2370e2c34f92f00628d48968dfea096d36381f494cbStephen Hines Msg->getReceiverKind() != ObjCMessageExpr::SuperInstance)) 238176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return false; 2390e2c34f92f00628d48968dfea096d36381f494cbStephen Hines if (const Expr *Receiver = Msg->getInstanceReceiver()) 2400e2c34f92f00628d48968dfea096d36381f494cbStephen Hines if (Receiver->getType()->isObjCBuiltinType()) 2410e2c34f92f00628d48968dfea096d36381f494cbStephen Hines return false; 2420e2c34f92f00628d48968dfea096d36381f494cbStephen Hines 243176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines const ObjCMethodDecl *Method = Msg->getMethodDecl(); 244176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (!Method) 245176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return false; 246176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (!Method->isPropertyAccessor()) 247176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return false; 248176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 249176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines const ObjCPropertyDecl *Prop = Method->findPropertyDecl(); 250176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (!Prop) 251176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return false; 252176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 253176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines SourceRange MsgRange = Msg->getSourceRange(); 2540e2c34f92f00628d48968dfea096d36381f494cbStephen Hines bool ReceiverIsSuper = 2550e2c34f92f00628d48968dfea096d36381f494cbStephen Hines (Msg->getReceiverKind() == ObjCMessageExpr::SuperInstance); 2560e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // for 'super' receiver is nullptr. 257176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines const Expr *receiver = Msg->getInstanceReceiver(); 2580e2c34f92f00628d48968dfea096d36381f494cbStephen Hines bool NeedsParen = 2590e2c34f92f00628d48968dfea096d36381f494cbStephen Hines ReceiverIsSuper ? false : subscriptOperatorNeedsParens(receiver); 260176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines bool IsGetter = (Msg->getNumArgs() == 0); 261176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (IsGetter) { 262176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines // Find space location range between receiver expression and getter method. 2630e2c34f92f00628d48968dfea096d36381f494cbStephen Hines SourceLocation BegLoc = 2640e2c34f92f00628d48968dfea096d36381f494cbStephen Hines ReceiverIsSuper ? Msg->getSuperLoc() : receiver->getLocEnd(); 265176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines BegLoc = PP.getLocForEndOfToken(BegLoc); 266176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines SourceLocation EndLoc = Msg->getSelectorLoc(0); 267176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines SourceRange SpaceRange(BegLoc, EndLoc); 268176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines std::string PropertyDotString; 269176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines // rewrite getter method expression into: receiver.property or 270176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines // (receiver).property 271176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (NeedsParen) { 272176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines commit.insertBefore(receiver->getLocStart(), "("); 273176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines PropertyDotString = ")."; 274176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 275176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines else 276176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines PropertyDotString = "."; 277176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines PropertyDotString += Prop->getName(); 278176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines commit.replace(SpaceRange, PropertyDotString); 279176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 280176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines // remove '[' ']' 281176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines commit.replace(SourceRange(MsgRange.getBegin(), MsgRange.getBegin()), ""); 282176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines commit.replace(SourceRange(MsgRange.getEnd(), MsgRange.getEnd()), ""); 283176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } else { 284176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (NeedsParen) 2850e2c34f92f00628d48968dfea096d36381f494cbStephen Hines commit.insertWrap("(", receiver->getSourceRange(), ")"); 286176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines std::string PropertyDotString = "."; 287176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines PropertyDotString += Prop->getName(); 288176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines PropertyDotString += " ="; 289176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines const Expr*const* Args = Msg->getArgs(); 290176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines const Expr *RHS = Args[0]; 291176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (!RHS) 292176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return false; 2930e2c34f92f00628d48968dfea096d36381f494cbStephen Hines SourceLocation BegLoc = 2940e2c34f92f00628d48968dfea096d36381f494cbStephen Hines ReceiverIsSuper ? Msg->getSuperLoc() : receiver->getLocEnd(); 295176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines BegLoc = PP.getLocForEndOfToken(BegLoc); 296176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines SourceLocation EndLoc = RHS->getLocStart(); 297176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines EndLoc = EndLoc.getLocWithOffset(-1); 2980e2c34f92f00628d48968dfea096d36381f494cbStephen Hines const char *colon = PP.getSourceManager().getCharacterData(EndLoc); 2990e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // Add a space after '=' if there is no space between RHS and '=' 3000e2c34f92f00628d48968dfea096d36381f494cbStephen Hines if (colon && colon[0] == ':') 3010e2c34f92f00628d48968dfea096d36381f494cbStephen Hines PropertyDotString += " "; 302176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines SourceRange Range(BegLoc, EndLoc); 303176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines commit.replace(Range, PropertyDotString); 304176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines // remove '[' ']' 305176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines commit.replace(SourceRange(MsgRange.getBegin(), MsgRange.getBegin()), ""); 306176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines commit.replace(SourceRange(MsgRange.getEnd(), MsgRange.getEnd()), ""); 307176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 308176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return true; 309176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 310176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 31130660a898545416f0fea2d717f16f75640001e38Ted Kremenekclass ObjCMigrator : public RecursiveASTVisitor<ObjCMigrator> { 31230660a898545416f0fea2d717f16f75640001e38Ted Kremenek ObjCMigrateASTConsumer &Consumer; 313a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis ParentMap &PMap; 31430660a898545416f0fea2d717f16f75640001e38Ted Kremenek 31530660a898545416f0fea2d717f16f75640001e38Ted Kremenekpublic: 316a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis ObjCMigrator(ObjCMigrateASTConsumer &consumer, ParentMap &PMap) 317a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis : Consumer(consumer), PMap(PMap) { } 31830660a898545416f0fea2d717f16f75640001e38Ted Kremenek 31930660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool shouldVisitTemplateInstantiations() const { return false; } 32030660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool shouldWalkTypesOfTypeLocs() const { return false; } 32130660a898545416f0fea2d717f16f75640001e38Ted Kremenek 32230660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool VisitObjCMessageExpr(ObjCMessageExpr *E) { 32374fd551c0ba344d62aedc8636ed81b45652f04d8Fariborz Jahanian if (Consumer.ASTMigrateActions & FrontendOptions::ObjCMT_Literals) { 32430660a898545416f0fea2d717f16f75640001e38Ted Kremenek edit::Commit commit(*Consumer.Editor); 325a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis edit::rewriteToObjCLiteralSyntax(E, *Consumer.NSAPIObj, commit, &PMap); 32630660a898545416f0fea2d717f16f75640001e38Ted Kremenek Consumer.Editor->commit(commit); 32730660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 32830660a898545416f0fea2d717f16f75640001e38Ted Kremenek 32974fd551c0ba344d62aedc8636ed81b45652f04d8Fariborz Jahanian if (Consumer.ASTMigrateActions & FrontendOptions::ObjCMT_Subscripting) { 33030660a898545416f0fea2d717f16f75640001e38Ted Kremenek edit::Commit commit(*Consumer.Editor); 33130660a898545416f0fea2d717f16f75640001e38Ted Kremenek edit::rewriteToObjCSubscriptSyntax(E, *Consumer.NSAPIObj, commit); 33230660a898545416f0fea2d717f16f75640001e38Ted Kremenek Consumer.Editor->commit(commit); 33330660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 33430660a898545416f0fea2d717f16f75640001e38Ted Kremenek 335176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (Consumer.ASTMigrateActions & FrontendOptions::ObjCMT_PropertyDotSyntax) { 336176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines edit::Commit commit(*Consumer.Editor); 337176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines rewriteToPropertyDotSyntax(E, Consumer.PP, *Consumer.NSAPIObj, 338176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines commit, &PMap); 339176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Consumer.Editor->commit(commit); 340176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 341176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 34230660a898545416f0fea2d717f16f75640001e38Ted Kremenek return true; 34330660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 34430660a898545416f0fea2d717f16f75640001e38Ted Kremenek 34530660a898545416f0fea2d717f16f75640001e38Ted Kremenek bool TraverseObjCMessageExpr(ObjCMessageExpr *E) { 34630660a898545416f0fea2d717f16f75640001e38Ted Kremenek // Do depth first; we want to rewrite the subexpressions first so that if 34730660a898545416f0fea2d717f16f75640001e38Ted Kremenek // we have to move expressions we will move them already rewritten. 34887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar for (Stmt *SubStmt : E->children()) 34987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if (!TraverseStmt(SubStmt)) 35030660a898545416f0fea2d717f16f75640001e38Ted Kremenek return false; 35130660a898545416f0fea2d717f16f75640001e38Ted Kremenek 35230660a898545416f0fea2d717f16f75640001e38Ted Kremenek return WalkUpFromObjCMessageExpr(E); 35330660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 35430660a898545416f0fea2d717f16f75640001e38Ted Kremenek}; 355a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis 356a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidisclass BodyMigrator : public RecursiveASTVisitor<BodyMigrator> { 357a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis ObjCMigrateASTConsumer &Consumer; 358651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::unique_ptr<ParentMap> PMap; 359a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis 360a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidispublic: 361a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis BodyMigrator(ObjCMigrateASTConsumer &consumer) : Consumer(consumer) { } 362a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis 363a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis bool shouldVisitTemplateInstantiations() const { return false; } 364a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis bool shouldWalkTypesOfTypeLocs() const { return false; } 365a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis 366a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis bool TraverseStmt(Stmt *S) { 367a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis PMap.reset(new ParentMap(S)); 368a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis ObjCMigrator(Consumer, *PMap).TraverseStmt(S); 369a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis return true; 370a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis } 371a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis}; 3724967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar} // end anonymous namespace 37330660a898545416f0fea2d717f16f75640001e38Ted Kremenek 37430660a898545416f0fea2d717f16f75640001e38Ted Kremenekvoid ObjCMigrateASTConsumer::migrateDecl(Decl *D) { 37530660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (!D) 37630660a898545416f0fea2d717f16f75640001e38Ted Kremenek return; 37730660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (isa<ObjCMethodDecl>(D)) 37830660a898545416f0fea2d717f16f75640001e38Ted Kremenek return; // Wait for the ObjC container declaration. 37930660a898545416f0fea2d717f16f75640001e38Ted Kremenek 380a44b97004298a4eb7c270009ea4cb12aad49c543Argyrios Kyrtzidis BodyMigrator(*this).TraverseDecl(D); 38130660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 38230660a898545416f0fea2d717f16f75640001e38Ted Kremenek 383624b367920405ac5ad5814eee41eb423c368a2c6Fariborz Jahanianstatic void append_attr(std::string &PropertyString, const char *attr, 384624b367920405ac5ad5814eee41eb423c368a2c6Fariborz Jahanian bool &LParenAdded) { 385624b367920405ac5ad5814eee41eb423c368a2c6Fariborz Jahanian if (!LParenAdded) { 386624b367920405ac5ad5814eee41eb423c368a2c6Fariborz Jahanian PropertyString += "("; 387624b367920405ac5ad5814eee41eb423c368a2c6Fariborz Jahanian LParenAdded = true; 388624b367920405ac5ad5814eee41eb423c368a2c6Fariborz Jahanian } 389624b367920405ac5ad5814eee41eb423c368a2c6Fariborz Jahanian else 390624b367920405ac5ad5814eee41eb423c368a2c6Fariborz Jahanian PropertyString += ", "; 391a9226496cd394efe36f1a774cf58e5a7f3eefd64Fariborz Jahanian PropertyString += attr; 392a9226496cd394efe36f1a774cf58e5a7f3eefd64Fariborz Jahanian} 393a9226496cd394efe36f1a774cf58e5a7f3eefd64Fariborz Jahanian 3942d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanianstatic 3952d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanianvoid MigrateBlockOrFunctionPointerTypeVariable(std::string & PropertyString, 3962d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian const std::string& TypeString, 3972d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian const char *name) { 3982d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian const char *argPtr = TypeString.c_str(); 3992d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian int paren = 0; 4002d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian while (*argPtr) { 4012d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian switch (*argPtr) { 4022d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian case '(': 4032d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian PropertyString += *argPtr; 4042d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian paren++; 4052d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian break; 4062d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian case ')': 4072d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian PropertyString += *argPtr; 4082d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian paren--; 4092d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian break; 4102d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian case '^': 411372877ef93f7bdfa5f4e48a82922450610c7052fFariborz Jahanian case '*': 412372877ef93f7bdfa5f4e48a82922450610c7052fFariborz Jahanian PropertyString += (*argPtr); 413372877ef93f7bdfa5f4e48a82922450610c7052fFariborz Jahanian if (paren == 1) { 4142d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian PropertyString += name; 415372877ef93f7bdfa5f4e48a82922450610c7052fFariborz Jahanian name = ""; 416372877ef93f7bdfa5f4e48a82922450610c7052fFariborz Jahanian } 4172d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian break; 4182d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian default: 4192d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian PropertyString += *argPtr; 4202d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian break; 4212d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian } 4222d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian argPtr++; 4232d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian } 4242d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian} 4252d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian 42693d4b8cbc7d55fcd3326747d07c7a65f42e02d93Fariborz Jahanianstatic const char *PropertyMemoryAttribute(ASTContext &Context, QualType ArgType) { 42793d4b8cbc7d55fcd3326747d07c7a65f42e02d93Fariborz Jahanian Qualifiers::ObjCLifetime propertyLifetime = ArgType.getObjCLifetime(); 42893d4b8cbc7d55fcd3326747d07c7a65f42e02d93Fariborz Jahanian bool RetainableObject = ArgType->isObjCRetainableType(); 429651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (RetainableObject && 430651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines (propertyLifetime == Qualifiers::OCL_Strong 431651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines || propertyLifetime == Qualifiers::OCL_None)) { 43293d4b8cbc7d55fcd3326747d07c7a65f42e02d93Fariborz Jahanian if (const ObjCObjectPointerType *ObjPtrTy = 43393d4b8cbc7d55fcd3326747d07c7a65f42e02d93Fariborz Jahanian ArgType->getAs<ObjCObjectPointerType>()) { 43493d4b8cbc7d55fcd3326747d07c7a65f42e02d93Fariborz Jahanian ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface(); 43593d4b8cbc7d55fcd3326747d07c7a65f42e02d93Fariborz Jahanian if (IDecl && 43693d4b8cbc7d55fcd3326747d07c7a65f42e02d93Fariborz Jahanian IDecl->lookupNestedProtocol(&Context.Idents.get("NSCopying"))) 43793d4b8cbc7d55fcd3326747d07c7a65f42e02d93Fariborz Jahanian return "copy"; 43893d4b8cbc7d55fcd3326747d07c7a65f42e02d93Fariborz Jahanian else 439651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return "strong"; 44093d4b8cbc7d55fcd3326747d07c7a65f42e02d93Fariborz Jahanian } 44193d4b8cbc7d55fcd3326747d07c7a65f42e02d93Fariborz Jahanian else if (ArgType->isBlockPointerType()) 44293d4b8cbc7d55fcd3326747d07c7a65f42e02d93Fariborz Jahanian return "copy"; 44393d4b8cbc7d55fcd3326747d07c7a65f42e02d93Fariborz Jahanian } else if (propertyLifetime == Qualifiers::OCL_Weak) 44493d4b8cbc7d55fcd3326747d07c7a65f42e02d93Fariborz Jahanian // TODO. More precise determination of 'weak' attribute requires 44593d4b8cbc7d55fcd3326747d07c7a65f42e02d93Fariborz Jahanian // looking into setter's implementation for backing weak ivar. 44693d4b8cbc7d55fcd3326747d07c7a65f42e02d93Fariborz Jahanian return "weak"; 44793d4b8cbc7d55fcd3326747d07c7a65f42e02d93Fariborz Jahanian else if (RetainableObject) 448651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return ArgType->isBlockPointerType() ? "copy" : "strong"; 4496bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 45093d4b8cbc7d55fcd3326747d07c7a65f42e02d93Fariborz Jahanian} 4512d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian 452b5b3f816d3c2543e11fb4f0b235041beafd81a1eFariborz Jahanianstatic void rewriteToObjCProperty(const ObjCMethodDecl *Getter, 45344b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian const ObjCMethodDecl *Setter, 454a9226496cd394efe36f1a774cf58e5a7f3eefd64Fariborz Jahanian const NSAPI &NS, edit::Commit &commit, 45539ebb02cb0bd342ced56de6d19aa9992aa0371b8Fariborz Jahanian unsigned LengthOfPrefix, 4565d2a20671954f55f765b96375e8bcd38367cb3baFariborz Jahanian bool Atomic, bool UseNsIosOnlyMacro, 4575d2a20671954f55f765b96375e8bcd38367cb3baFariborz Jahanian bool AvailabilityArgsMatch) { 45844b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian ASTContext &Context = NS.getASTContext(); 459624b367920405ac5ad5814eee41eb423c368a2c6Fariborz Jahanian bool LParenAdded = false; 460624b367920405ac5ad5814eee41eb423c368a2c6Fariborz Jahanian std::string PropertyString = "@property "; 461b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar if (UseNsIosOnlyMacro && NS.isMacroDefined("NS_NONATOMIC_IOSONLY")) { 4621ab853d934daefee1806872a2d4a5f0fe0ff1939Fariborz Jahanian PropertyString += "(NS_NONATOMIC_IOSONLY"; 4631ab853d934daefee1806872a2d4a5f0fe0ff1939Fariborz Jahanian LParenAdded = true; 4641ab853d934daefee1806872a2d4a5f0fe0ff1939Fariborz Jahanian } else if (!Atomic) { 465624b367920405ac5ad5814eee41eb423c368a2c6Fariborz Jahanian PropertyString += "(nonatomic"; 466624b367920405ac5ad5814eee41eb423c368a2c6Fariborz Jahanian LParenAdded = true; 467624b367920405ac5ad5814eee41eb423c368a2c6Fariborz Jahanian } 468624b367920405ac5ad5814eee41eb423c368a2c6Fariborz Jahanian 469fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian std::string PropertyNameString = Getter->getNameAsString(); 470fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian StringRef PropertyName(PropertyNameString); 471a81f102bd396fd1da61b47337a2389f352baf539Fariborz Jahanian if (LengthOfPrefix > 0) { 472624b367920405ac5ad5814eee41eb423c368a2c6Fariborz Jahanian if (!LParenAdded) { 473624b367920405ac5ad5814eee41eb423c368a2c6Fariborz Jahanian PropertyString += "(getter="; 474624b367920405ac5ad5814eee41eb423c368a2c6Fariborz Jahanian LParenAdded = true; 475624b367920405ac5ad5814eee41eb423c368a2c6Fariborz Jahanian } 476624b367920405ac5ad5814eee41eb423c368a2c6Fariborz Jahanian else 477624b367920405ac5ad5814eee41eb423c368a2c6Fariborz Jahanian PropertyString += ", getter="; 478a9226496cd394efe36f1a774cf58e5a7f3eefd64Fariborz Jahanian PropertyString += PropertyNameString; 479a9226496cd394efe36f1a774cf58e5a7f3eefd64Fariborz Jahanian } 4805b98aba1d74184923da32016c3abbc20e9a7686dFariborz Jahanian // Property with no setter may be suggested as a 'readonly' property. 481651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!Setter) 48293d4b8cbc7d55fcd3326747d07c7a65f42e02d93Fariborz Jahanian append_attr(PropertyString, "readonly", LParenAdded); 483651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 4842d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian 485803ccc9071a7120b20490ba0f2ca2ed7d9e96c45Fariborz Jahanian // Short circuit 'delegate' properties that contain the name "delegate" or 486803ccc9071a7120b20490ba0f2ca2ed7d9e96c45Fariborz Jahanian // "dataSource", or have exact name "target" to have 'assign' attribute. 487fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian if (PropertyName.equals("target") || 488fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian (PropertyName.find("delegate") != StringRef::npos) || 489b81765f59f0c99da3b4e934686bfc118b91aded0Fariborz Jahanian (PropertyName.find("dataSource") != StringRef::npos)) { 490651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines QualType QT = Getter->getReturnType(); 491b81765f59f0c99da3b4e934686bfc118b91aded0Fariborz Jahanian if (!QT->isRealType()) 492b81765f59f0c99da3b4e934686bfc118b91aded0Fariborz Jahanian append_attr(PropertyString, "assign", LParenAdded); 493651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } else if (!Setter) { 494651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines QualType ResType = Context.getCanonicalType(Getter->getReturnType()); 495651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (const char *MemoryManagementAttr = PropertyMemoryAttribute(Context, ResType)) 496651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines append_attr(PropertyString, MemoryManagementAttr, LParenAdded); 497651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } else { 498fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian const ParmVarDecl *argDecl = *Setter->param_begin(); 499fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian QualType ArgType = Context.getCanonicalType(argDecl->getType()); 50093d4b8cbc7d55fcd3326747d07c7a65f42e02d93Fariborz Jahanian if (const char *MemoryManagementAttr = PropertyMemoryAttribute(Context, ArgType)) 50193d4b8cbc7d55fcd3326747d07c7a65f42e02d93Fariborz Jahanian append_attr(PropertyString, MemoryManagementAttr, LParenAdded); 502fa45cb3bf95a10d6c3b1ab55d60dae28e8a57cf4Fariborz Jahanian } 503624b367920405ac5ad5814eee41eb423c368a2c6Fariborz Jahanian if (LParenAdded) 504624b367920405ac5ad5814eee41eb423c368a2c6Fariborz Jahanian PropertyString += ')'; 505651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines QualType RT = Getter->getReturnType(); 506a9226496cd394efe36f1a774cf58e5a7f3eefd64Fariborz Jahanian if (!isa<TypedefType>(RT)) { 507a9226496cd394efe36f1a774cf58e5a7f3eefd64Fariborz Jahanian // strip off any ARC lifetime qualifier. 508a9226496cd394efe36f1a774cf58e5a7f3eefd64Fariborz Jahanian QualType CanResultTy = Context.getCanonicalType(RT); 509a9226496cd394efe36f1a774cf58e5a7f3eefd64Fariborz Jahanian if (CanResultTy.getQualifiers().hasObjCLifetime()) { 510a9226496cd394efe36f1a774cf58e5a7f3eefd64Fariborz Jahanian Qualifiers Qs = CanResultTy.getQualifiers(); 511a9226496cd394efe36f1a774cf58e5a7f3eefd64Fariborz Jahanian Qs.removeObjCLifetime(); 512a9226496cd394efe36f1a774cf58e5a7f3eefd64Fariborz Jahanian RT = Context.getQualifiedType(CanResultTy.getUnqualifiedType(), Qs); 513a9226496cd394efe36f1a774cf58e5a7f3eefd64Fariborz Jahanian } 51444b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian } 51544b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian PropertyString += " "; 5162d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian PrintingPolicy SubPolicy(Context.getPrintingPolicy()); 5172d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian SubPolicy.SuppressStrongLifetime = true; 5189fe529f15723018a2fecdcc35611210f92ed2b82Fariborz Jahanian SubPolicy.SuppressLifetimeQualifiers = true; 5192d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian std::string TypeString = RT.getAsString(SubPolicy); 520a81f102bd396fd1da61b47337a2389f352baf539Fariborz Jahanian if (LengthOfPrefix > 0) { 521a9226496cd394efe36f1a774cf58e5a7f3eefd64Fariborz Jahanian // property name must strip off "is" and lower case the first character 522a9226496cd394efe36f1a774cf58e5a7f3eefd64Fariborz Jahanian // after that; e.g. isContinuous will become continuous. 523a9226496cd394efe36f1a774cf58e5a7f3eefd64Fariborz Jahanian StringRef PropertyNameStringRef(PropertyNameString); 524a81f102bd396fd1da61b47337a2389f352baf539Fariborz Jahanian PropertyNameStringRef = PropertyNameStringRef.drop_front(LengthOfPrefix); 525a9226496cd394efe36f1a774cf58e5a7f3eefd64Fariborz Jahanian PropertyNameString = PropertyNameStringRef; 5262d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian bool NoLowering = (isUppercase(PropertyNameString[0]) && 5272d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian PropertyNameString.size() > 1 && 5282d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian isUppercase(PropertyNameString[1])); 529e80501ba640fae189d5f944b025a0079ec3c579fFariborz Jahanian if (!NoLowering) 5302d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian PropertyNameString[0] = toLowercase(PropertyNameString[0]); 531a9226496cd394efe36f1a774cf58e5a7f3eefd64Fariborz Jahanian } 5322d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian if (RT->isBlockPointerType() || RT->isFunctionPointerType()) 5332d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian MigrateBlockOrFunctionPointerTypeVariable(PropertyString, 5342d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian TypeString, 5352d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian PropertyNameString.c_str()); 5362d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian else { 5372d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian char LastChar = TypeString[TypeString.size()-1]; 5382d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian PropertyString += TypeString; 5392d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian if (LastChar != '*') 5402d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian PropertyString += ' '; 541a9226496cd394efe36f1a774cf58e5a7f3eefd64Fariborz Jahanian PropertyString += PropertyNameString; 5422d9f38a47c86cd462ee8fa82210f27a8f9e0d2b7Fariborz Jahanian } 5438451a458d65879bb594ee879353658723feda0eeFariborz Jahanian SourceLocation StartGetterSelectorLoc = Getter->getSelectorStartLoc(); 5448451a458d65879bb594ee879353658723feda0eeFariborz Jahanian Selector GetterSelector = Getter->getSelector(); 5458451a458d65879bb594ee879353658723feda0eeFariborz Jahanian 5468451a458d65879bb594ee879353658723feda0eeFariborz Jahanian SourceLocation EndGetterSelectorLoc = 5478451a458d65879bb594ee879353658723feda0eeFariborz Jahanian StartGetterSelectorLoc.getLocWithOffset(GetterSelector.getNameForSlot(0).size()); 54844b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian commit.replace(CharSourceRange::getCharRange(Getter->getLocStart(), 5498451a458d65879bb594ee879353658723feda0eeFariborz Jahanian EndGetterSelectorLoc), 55044b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian PropertyString); 551257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian if (Setter && AvailabilityArgsMatch) { 5525b98aba1d74184923da32016c3abbc20e9a7686dFariborz Jahanian SourceLocation EndLoc = Setter->getDeclaratorEndLoc(); 5535b98aba1d74184923da32016c3abbc20e9a7686dFariborz Jahanian // Get location past ';' 5545b98aba1d74184923da32016c3abbc20e9a7686dFariborz Jahanian EndLoc = EndLoc.getLocWithOffset(1); 555b5b3f816d3c2543e11fb4f0b235041beafd81a1eFariborz Jahanian SourceLocation BeginOfSetterDclLoc = Setter->getLocStart(); 556651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // FIXME. This assumes that setter decl; is immediately preceded by eoln. 557b5b3f816d3c2543e11fb4f0b235041beafd81a1eFariborz Jahanian // It is trying to remove the setter method decl. line entirely. 558b5b3f816d3c2543e11fb4f0b235041beafd81a1eFariborz Jahanian BeginOfSetterDclLoc = BeginOfSetterDclLoc.getLocWithOffset(-1); 559b5b3f816d3c2543e11fb4f0b235041beafd81a1eFariborz Jahanian commit.remove(SourceRange(BeginOfSetterDclLoc, EndLoc)); 5605b98aba1d74184923da32016c3abbc20e9a7686dFariborz Jahanian } 56144b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian} 56244b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian 563651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic bool IsCategoryNameWithDeprecatedSuffix(ObjCContainerDecl *D) { 564651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(D)) { 565651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines StringRef Name = CatDecl->getName(); 566651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return Name.endswith("Deprecated"); 567651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 568651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return false; 569651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 570651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 57158878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainarvoid ObjCMigrateASTConsumer::migrateObjCContainerDecl(ASTContext &Ctx, 5729c4759149c80464ca26dcc90c756f439e6640684Fariborz Jahanian ObjCContainerDecl *D) { 573651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (D->isDeprecated() || IsCategoryNameWithDeprecatedSuffix(D)) 574641645f00c22e1f55794537a43646214402e99a1Fariborz Jahanian return; 575651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 576651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto *Method : D->methods()) { 577641645f00c22e1f55794537a43646214402e99a1Fariborz Jahanian if (Method->isDeprecated()) 578641645f00c22e1f55794537a43646214402e99a1Fariborz Jahanian continue; 57978e39b0b69ee5af1d9691f3143de15cb37b8ad55Fariborz Jahanian bool PropertyInferred = migrateProperty(Ctx, D, Method); 58078e39b0b69ee5af1d9691f3143de15cb37b8ad55Fariborz Jahanian // If a property is inferred, do not attempt to attach NS_RETURNS_INNER_POINTER to 58178e39b0b69ee5af1d9691f3143de15cb37b8ad55Fariborz Jahanian // the getter method as it ends up on the property itself which we don't want 58278e39b0b69ee5af1d9691f3143de15cb37b8ad55Fariborz Jahanian // to do unless -objcmt-returns-innerpointer-property option is on. 58378e39b0b69ee5af1d9691f3143de15cb37b8ad55Fariborz Jahanian if (!PropertyInferred || 58478e39b0b69ee5af1d9691f3143de15cb37b8ad55Fariborz Jahanian (ASTMigrateActions & FrontendOptions::ObjCMT_ReturnsInnerPointerProperty)) 58580aecf578fa0b24e1f4280820a1b6f1bf34862e0Fariborz Jahanian if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) 58680aecf578fa0b24e1f4280820a1b6f1bf34862e0Fariborz Jahanian migrateNsReturnsInnerPointer(Ctx, Method); 587f85f5e4769730e06590d969ad3cbff879d8006f6Fariborz Jahanian } 588cd569f2788ece55b9f790b6900164e2b2d5d966cFariborz Jahanian if (!(ASTMigrateActions & FrontendOptions::ObjCMT_ReturnsInnerPointerProperty)) 589cd569f2788ece55b9f790b6900164e2b2d5d966cFariborz Jahanian return; 590cd569f2788ece55b9f790b6900164e2b2d5d966cFariborz Jahanian 5914967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar for (auto *Prop : D->instance_properties()) { 592b8941a15b6b5477a81c189614d0129070ac099f1Fariborz Jahanian if ((ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) && 5936d754e9a9d6591e8fc5eedc144cc70a7e539ba6fFariborz Jahanian !Prop->isDeprecated()) 594f85f5e4769730e06590d969ad3cbff879d8006f6Fariborz Jahanian migratePropertyNsReturnsInnerPointer(Ctx, Prop); 595baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian } 596baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian} 597baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian 5986d754e9a9d6591e8fc5eedc144cc70a7e539ba6fFariborz Jahanianstatic bool 599bf13df238a82659c0b6363541a84f09bc997fb86Fariborz JahanianClassImplementsAllMethodsAndProperties(ASTContext &Ctx, 600e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian const ObjCImplementationDecl *ImpDecl, 601ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian const ObjCInterfaceDecl *IDecl, 602e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian ObjCProtocolDecl *Protocol) { 603ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian // In auto-synthesis, protocol properties are not synthesized. So, 604ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian // a conforming protocol must have its required properties declared 605ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian // in class interface. 60634cb2a3ed535eebed87d1118e89d006eb324e156Fariborz Jahanian bool HasAtleastOneRequiredProperty = false; 607ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian if (const ObjCProtocolDecl *PDecl = Protocol->getDefinition()) 6084967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar for (const auto *Property : PDecl->instance_properties()) { 609ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian if (Property->getPropertyImplementation() == ObjCPropertyDecl::Optional) 610ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian continue; 61134cb2a3ed535eebed87d1118e89d006eb324e156Fariborz Jahanian HasAtleastOneRequiredProperty = true; 6120e2c34f92f00628d48968dfea096d36381f494cbStephen Hines DeclContext::lookup_result R = IDecl->lookup(Property->getDeclName()); 6138d8bfb3e52567b86add4bfa931023f2e2a291499Fariborz Jahanian if (R.size() == 0) { 6148d8bfb3e52567b86add4bfa931023f2e2a291499Fariborz Jahanian // Relax the rule and look into class's implementation for a synthesize 6158d8bfb3e52567b86add4bfa931023f2e2a291499Fariborz Jahanian // or dynamic declaration. Class is implementing a property coming from 6168d8bfb3e52567b86add4bfa931023f2e2a291499Fariborz Jahanian // another protocol. This still makes the target protocol as conforming. 6178d8bfb3e52567b86add4bfa931023f2e2a291499Fariborz Jahanian if (!ImpDecl->FindPropertyImplDecl( 6184967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Property->getDeclName().getAsIdentifierInfo(), 6194967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar Property->getQueryKind())) 6208d8bfb3e52567b86add4bfa931023f2e2a291499Fariborz Jahanian return false; 6218d8bfb3e52567b86add4bfa931023f2e2a291499Fariborz Jahanian } 6228d8bfb3e52567b86add4bfa931023f2e2a291499Fariborz Jahanian else if (ObjCPropertyDecl *ClassProperty = dyn_cast<ObjCPropertyDecl>(R[0])) { 6238d8bfb3e52567b86add4bfa931023f2e2a291499Fariborz Jahanian if ((ClassProperty->getPropertyAttributes() 6248d8bfb3e52567b86add4bfa931023f2e2a291499Fariborz Jahanian != Property->getPropertyAttributes()) || 6258d8bfb3e52567b86add4bfa931023f2e2a291499Fariborz Jahanian !Ctx.hasSameType(ClassProperty->getType(), Property->getType())) 626ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian return false; 627ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian } 6288d8bfb3e52567b86add4bfa931023f2e2a291499Fariborz Jahanian else 6298d8bfb3e52567b86add4bfa931023f2e2a291499Fariborz Jahanian return false; 630ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian } 63134cb2a3ed535eebed87d1118e89d006eb324e156Fariborz Jahanian 632ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian // At this point, all required properties in this protocol conform to those 633ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian // declared in the class. 634ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian // Check that class implements the required methods of the protocol too. 63534cb2a3ed535eebed87d1118e89d006eb324e156Fariborz Jahanian bool HasAtleastOneRequiredMethod = false; 6368c355831ac3c9e8c12b23ca69b7587dcbd0439efFariborz Jahanian if (const ObjCProtocolDecl *PDecl = Protocol->getDefinition()) { 6378c355831ac3c9e8c12b23ca69b7587dcbd0439efFariborz Jahanian if (PDecl->meth_begin() == PDecl->meth_end()) 63834cb2a3ed535eebed87d1118e89d006eb324e156Fariborz Jahanian return HasAtleastOneRequiredProperty; 639651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto *MD : PDecl->methods()) { 6408c355831ac3c9e8c12b23ca69b7587dcbd0439efFariborz Jahanian if (MD->isImplicit()) 6418c355831ac3c9e8c12b23ca69b7587dcbd0439efFariborz Jahanian continue; 642ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian if (MD->getImplementationControl() == ObjCMethodDecl::Optional) 643ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian continue; 6440e2c34f92f00628d48968dfea096d36381f494cbStephen Hines DeclContext::lookup_result R = ImpDecl->lookup(MD->getDeclName()); 6458c355831ac3c9e8c12b23ca69b7587dcbd0439efFariborz Jahanian if (R.size() == 0) 6468c355831ac3c9e8c12b23ca69b7587dcbd0439efFariborz Jahanian return false; 64734cb2a3ed535eebed87d1118e89d006eb324e156Fariborz Jahanian bool match = false; 64834cb2a3ed535eebed87d1118e89d006eb324e156Fariborz Jahanian HasAtleastOneRequiredMethod = true; 649ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian for (unsigned I = 0, N = R.size(); I != N; ++I) 650ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian if (ObjCMethodDecl *ImpMD = dyn_cast<ObjCMethodDecl>(R[0])) 651ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian if (Ctx.ObjCMethodsAreEqual(MD, ImpMD)) { 652ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian match = true; 653ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian break; 654ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian } 655ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian if (!match) 656ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian return false; 657ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian } 6588c355831ac3c9e8c12b23ca69b7587dcbd0439efFariborz Jahanian } 65987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return HasAtleastOneRequiredProperty || HasAtleastOneRequiredMethod; 660e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian} 661e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian 66244b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanianstatic bool rewriteToObjCInterfaceDecl(const ObjCInterfaceDecl *IDecl, 66344b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian llvm::SmallVectorImpl<ObjCProtocolDecl*> &ConformingProtocols, 66444b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian const NSAPI &NS, edit::Commit &commit) { 66544b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian const ObjCList<ObjCProtocolDecl> &Protocols = IDecl->getReferencedProtocols(); 66644b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian std::string ClassString; 66744b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian SourceLocation EndLoc = 66844b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian IDecl->getSuperClass() ? IDecl->getSuperClassLoc() : IDecl->getLocation(); 66944b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian 67044b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian if (Protocols.empty()) { 67144b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian ClassString = '<'; 67244b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) { 67344b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian ClassString += ConformingProtocols[i]->getNameAsString(); 67444b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian if (i != (e-1)) 67544b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian ClassString += ", "; 67644b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian } 67744b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian ClassString += "> "; 67844b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian } 67944b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian else { 68044b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian ClassString = ", "; 68144b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) { 68244b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian ClassString += ConformingProtocols[i]->getNameAsString(); 68344b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian if (i != (e-1)) 68444b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian ClassString += ", "; 68544b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian } 68644b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian ObjCInterfaceDecl::protocol_loc_iterator PL = IDecl->protocol_loc_end() - 1; 68744b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian EndLoc = *PL; 68844b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian } 68944b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian 69044b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian commit.insertAfterToken(EndLoc, ClassString); 69144b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian return true; 69244b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian} 69344b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian 694176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesstatic StringRef GetUnsignedName(StringRef NSIntegerName) { 695176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines StringRef UnsignedName = llvm::StringSwitch<StringRef>(NSIntegerName) 696176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines .Case("int8_t", "uint8_t") 697176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines .Case("int16_t", "uint16_t") 698176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines .Case("int32_t", "uint32_t") 699176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines .Case("NSInteger", "NSUInteger") 700176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines .Case("int64_t", "uint64_t") 701176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines .Default(NSIntegerName); 702176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return UnsignedName; 703176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines} 704176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 70544b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanianstatic bool rewriteToNSEnumDecl(const EnumDecl *EnumDcl, 70644b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian const TypedefDecl *TypedefDcl, 7079f9e54390c255587b009d912007b139432ab7bdcFariborz Jahanian const NSAPI &NS, edit::Commit &commit, 708176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines StringRef NSIntegerName, 709c9820ebfeff30598ebd7369c5daf5bde10df934bFariborz Jahanian bool NSOptions) { 710c9820ebfeff30598ebd7369c5daf5bde10df934bFariborz Jahanian std::string ClassString; 711176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (NSOptions) { 712176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines ClassString = "typedef NS_OPTIONS("; 713176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines ClassString += GetUnsignedName(NSIntegerName); 714176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 715176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines else { 716176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines ClassString = "typedef NS_ENUM("; 717176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines ClassString += NSIntegerName; 718176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 719176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines ClassString += ", "; 720c9820ebfeff30598ebd7369c5daf5bde10df934bFariborz Jahanian 72144b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian ClassString += TypedefDcl->getIdentifier()->getName(); 72244b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian ClassString += ')'; 72344b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian SourceRange R(EnumDcl->getLocStart(), EnumDcl->getLocStart()); 72444b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian commit.replace(R, ClassString); 725b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian SourceLocation EndOfEnumDclLoc = EnumDcl->getLocEnd(); 726b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian EndOfEnumDclLoc = trans::findSemiAfterLocation(EndOfEnumDclLoc, 727b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian NS.getASTContext(), /*IsDecl*/true); 72887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if (EndOfEnumDclLoc.isValid()) { 729b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian SourceRange EnumDclRange(EnumDcl->getLocStart(), EndOfEnumDclLoc); 730b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian commit.insertFromRange(TypedefDcl->getLocStart(), EnumDclRange); 731b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian } 732b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian else 733b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian return false; 734b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian 735b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian SourceLocation EndTypedefDclLoc = TypedefDcl->getLocEnd(); 736b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian EndTypedefDclLoc = trans::findSemiAfterLocation(EndTypedefDclLoc, 737b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian NS.getASTContext(), /*IsDecl*/true); 73887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if (EndTypedefDclLoc.isValid()) { 739b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian SourceRange TDRange(TypedefDcl->getLocStart(), EndTypedefDclLoc); 740b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian commit.remove(TDRange); 741b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian } 742b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian else 743b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian return false; 744b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian 745b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian EndOfEnumDclLoc = trans::findLocationAfterSemi(EnumDcl->getLocEnd(), NS.getASTContext(), 7461f9a09d4e50c3e8e622292350823eef776b93e3dFariborz Jahanian /*IsDecl*/true); 74787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if (EndOfEnumDclLoc.isValid()) { 748b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian SourceLocation BeginOfEnumDclLoc = EnumDcl->getLocStart(); 749651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // FIXME. This assumes that enum decl; is immediately preceded by eoln. 750b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian // It is trying to remove the enum decl. lines entirely. 751b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian BeginOfEnumDclLoc = BeginOfEnumDclLoc.getLocWithOffset(-1); 752b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian commit.remove(SourceRange(BeginOfEnumDclLoc, EndOfEnumDclLoc)); 75344b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian return true; 75444b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian } 75544b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian return false; 75644b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian} 75744b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian 7580e2c34f92f00628d48968dfea096d36381f494cbStephen Hinesstatic void rewriteToNSMacroDecl(ASTContext &Ctx, 7590e2c34f92f00628d48968dfea096d36381f494cbStephen Hines const EnumDecl *EnumDcl, 760faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian const TypedefDecl *TypedefDcl, 761e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian const NSAPI &NS, edit::Commit &commit, 762e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian bool IsNSIntegerType) { 7633ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar QualType DesignatedEnumType = EnumDcl->getIntegerType(); 7643ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar assert(!DesignatedEnumType.isNull() 7650e2c34f92f00628d48968dfea096d36381f494cbStephen Hines && "rewriteToNSMacroDecl - underlying enum type is null"); 7660e2c34f92f00628d48968dfea096d36381f494cbStephen Hines 7670e2c34f92f00628d48968dfea096d36381f494cbStephen Hines PrintingPolicy Policy(Ctx.getPrintingPolicy()); 7683ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar std::string TypeString = DesignatedEnumType.getAsString(Policy); 7690e2c34f92f00628d48968dfea096d36381f494cbStephen Hines std::string ClassString = IsNSIntegerType ? "NS_ENUM(" : "NS_OPTIONS("; 7700e2c34f92f00628d48968dfea096d36381f494cbStephen Hines ClassString += TypeString; 7710e2c34f92f00628d48968dfea096d36381f494cbStephen Hines ClassString += ", "; 7720e2c34f92f00628d48968dfea096d36381f494cbStephen Hines 773faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian ClassString += TypedefDcl->getIdentifier()->getName(); 774faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian ClassString += ')'; 7750e2c34f92f00628d48968dfea096d36381f494cbStephen Hines SourceLocation EndLoc; 7760e2c34f92f00628d48968dfea096d36381f494cbStephen Hines if (EnumDcl->getIntegerTypeSourceInfo()) { 7770e2c34f92f00628d48968dfea096d36381f494cbStephen Hines TypeSourceInfo *TSourceInfo = EnumDcl->getIntegerTypeSourceInfo(); 7780e2c34f92f00628d48968dfea096d36381f494cbStephen Hines TypeLoc TLoc = TSourceInfo->getTypeLoc(); 7790e2c34f92f00628d48968dfea096d36381f494cbStephen Hines EndLoc = TLoc.getLocEnd(); 7800e2c34f92f00628d48968dfea096d36381f494cbStephen Hines const char *lbrace = Ctx.getSourceManager().getCharacterData(EndLoc); 7810e2c34f92f00628d48968dfea096d36381f494cbStephen Hines unsigned count = 0; 7820e2c34f92f00628d48968dfea096d36381f494cbStephen Hines if (lbrace) 7830e2c34f92f00628d48968dfea096d36381f494cbStephen Hines while (lbrace[count] != '{') 7840e2c34f92f00628d48968dfea096d36381f494cbStephen Hines ++count; 7850e2c34f92f00628d48968dfea096d36381f494cbStephen Hines if (count > 0) 7860e2c34f92f00628d48968dfea096d36381f494cbStephen Hines EndLoc = EndLoc.getLocWithOffset(count-1); 7870e2c34f92f00628d48968dfea096d36381f494cbStephen Hines } 7880e2c34f92f00628d48968dfea096d36381f494cbStephen Hines else 7890e2c34f92f00628d48968dfea096d36381f494cbStephen Hines EndLoc = EnumDcl->getLocStart(); 7900e2c34f92f00628d48968dfea096d36381f494cbStephen Hines SourceRange R(EnumDcl->getLocStart(), EndLoc); 791faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian commit.replace(R, ClassString); 792176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines // This is to remove spaces between '}' and typedef name. 793176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines SourceLocation StartTypedefLoc = EnumDcl->getLocEnd(); 794176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines StartTypedefLoc = StartTypedefLoc.getLocWithOffset(+1); 795176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines SourceLocation EndTypedefLoc = TypedefDcl->getLocEnd(); 796176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 797176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines commit.remove(SourceRange(StartTypedefLoc, EndTypedefLoc)); 798faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian} 799faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian 800ad162e912db93be9494ba3ebc12994e51e0b0db2Fariborz Jahanianstatic bool UseNSOptionsMacro(Preprocessor &PP, ASTContext &Ctx, 801e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian const EnumDecl *EnumDcl) { 802e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian bool PowerOfTwo = true; 803ff89d06413ff79fb2314b9196fa2508e244159fcFariborz Jahanian bool AllHexdecimalEnumerator = true; 8040b5941c2a6ce99f0dc0dc8b64024eeabbbb6db1dFariborz Jahanian uint64_t MaxPowerOfTwoVal = 0; 805651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto Enumerator : EnumDcl->enumerators()) { 806e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian const Expr *InitExpr = Enumerator->getInitExpr(); 807e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian if (!InitExpr) { 808e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian PowerOfTwo = false; 809ff89d06413ff79fb2314b9196fa2508e244159fcFariborz Jahanian AllHexdecimalEnumerator = false; 810e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian continue; 811e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian } 812bb2405f293c79732748282538198e1d2d0f1b459Fariborz Jahanian InitExpr = InitExpr->IgnoreParenCasts(); 813e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(InitExpr)) 814e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian if (BO->isShiftOp() || BO->isBitwiseOp()) 815e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian return true; 816e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian 817e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian uint64_t EnumVal = Enumerator->getInitVal().getZExtValue(); 8180b5941c2a6ce99f0dc0dc8b64024eeabbbb6db1dFariborz Jahanian if (PowerOfTwo && EnumVal) { 8190b5941c2a6ce99f0dc0dc8b64024eeabbbb6db1dFariborz Jahanian if (!llvm::isPowerOf2_64(EnumVal)) 8200b5941c2a6ce99f0dc0dc8b64024eeabbbb6db1dFariborz Jahanian PowerOfTwo = false; 8210b5941c2a6ce99f0dc0dc8b64024eeabbbb6db1dFariborz Jahanian else if (EnumVal > MaxPowerOfTwoVal) 8220b5941c2a6ce99f0dc0dc8b64024eeabbbb6db1dFariborz Jahanian MaxPowerOfTwoVal = EnumVal; 8230b5941c2a6ce99f0dc0dc8b64024eeabbbb6db1dFariborz Jahanian } 824ff89d06413ff79fb2314b9196fa2508e244159fcFariborz Jahanian if (AllHexdecimalEnumerator && EnumVal) { 825ff89d06413ff79fb2314b9196fa2508e244159fcFariborz Jahanian bool FoundHexdecimalEnumerator = false; 826ad162e912db93be9494ba3ebc12994e51e0b0db2Fariborz Jahanian SourceLocation EndLoc = Enumerator->getLocEnd(); 827ad162e912db93be9494ba3ebc12994e51e0b0db2Fariborz Jahanian Token Tok; 828ad162e912db93be9494ba3ebc12994e51e0b0db2Fariborz Jahanian if (!PP.getRawToken(EndLoc, Tok, /*IgnoreWhiteSpace=*/true)) 829ad162e912db93be9494ba3ebc12994e51e0b0db2Fariborz Jahanian if (Tok.isLiteral() && Tok.getLength() > 2) { 830ad162e912db93be9494ba3ebc12994e51e0b0db2Fariborz Jahanian if (const char *StringLit = Tok.getLiteralData()) 831ad162e912db93be9494ba3ebc12994e51e0b0db2Fariborz Jahanian FoundHexdecimalEnumerator = 832ad162e912db93be9494ba3ebc12994e51e0b0db2Fariborz Jahanian (StringLit[0] == '0' && (toLowercase(StringLit[1]) == 'x')); 833ad162e912db93be9494ba3ebc12994e51e0b0db2Fariborz Jahanian } 834ff89d06413ff79fb2314b9196fa2508e244159fcFariborz Jahanian if (!FoundHexdecimalEnumerator) 835ff89d06413ff79fb2314b9196fa2508e244159fcFariborz Jahanian AllHexdecimalEnumerator = false; 836ad162e912db93be9494ba3ebc12994e51e0b0db2Fariborz Jahanian } 837e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian } 838ff89d06413ff79fb2314b9196fa2508e244159fcFariborz Jahanian return AllHexdecimalEnumerator || (PowerOfTwo && (MaxPowerOfTwoVal > 2)); 839e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian} 840e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian 84172685630b693c0ba6050875128ff6bb18107ba2fFariborz Jahanianvoid ObjCMigrateASTConsumer::migrateProtocolConformance(ASTContext &Ctx, 8427556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian const ObjCImplementationDecl *ImpDecl) { 8437556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian const ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface(); 844641645f00c22e1f55794537a43646214402e99a1Fariborz Jahanian if (!IDecl || ObjCProtocolDecls.empty() || IDecl->isDeprecated()) 8457556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian return; 8467556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian // Find all implicit conforming protocols for this class 8477556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian // and make them explicit. 8487556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian llvm::SmallPtrSet<ObjCProtocolDecl *, 8> ExplicitProtocols; 8497556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian Ctx.CollectInheritedProtocols(IDecl, ExplicitProtocols); 850e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian llvm::SmallVector<ObjCProtocolDecl *, 8> PotentialImplicitProtocols; 8517556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian 852176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines for (ObjCProtocolDecl *ProtDecl : ObjCProtocolDecls) 853176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (!ExplicitProtocols.count(ProtDecl)) 854176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines PotentialImplicitProtocols.push_back(ProtDecl); 8557556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian 8567556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian if (PotentialImplicitProtocols.empty()) 8577556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian return; 858e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian 859e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian // go through list of non-optional methods and properties in each protocol 860e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian // in the PotentialImplicitProtocols list. If class implements every one of the 861e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian // methods and properties, then this class conforms to this protocol. 862e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian llvm::SmallVector<ObjCProtocolDecl*, 8> ConformingProtocols; 863e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian for (unsigned i = 0, e = PotentialImplicitProtocols.size(); i != e; i++) 864ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian if (ClassImplementsAllMethodsAndProperties(Ctx, ImpDecl, IDecl, 865e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian PotentialImplicitProtocols[i])) 866e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian ConformingProtocols.push_back(PotentialImplicitProtocols[i]); 8678c355831ac3c9e8c12b23ca69b7587dcbd0439efFariborz Jahanian 8688c355831ac3c9e8c12b23ca69b7587dcbd0439efFariborz Jahanian if (ConformingProtocols.empty()) 8698c355831ac3c9e8c12b23ca69b7587dcbd0439efFariborz Jahanian return; 870e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian 871e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian // Further reduce number of conforming protocols. If protocol P1 is in the list 872e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian // protocol P2 (P2<P1>), No need to include P1. 873e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian llvm::SmallVector<ObjCProtocolDecl*, 8> MinimalConformingProtocols; 874e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) { 875e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian bool DropIt = false; 876e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian ObjCProtocolDecl *TargetPDecl = ConformingProtocols[i]; 877e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian for (unsigned i1 = 0, e1 = ConformingProtocols.size(); i1 != e1; i1++) { 878e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian ObjCProtocolDecl *PDecl = ConformingProtocols[i1]; 879e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian if (PDecl == TargetPDecl) 880e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian continue; 881e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian if (PDecl->lookupProtocolNamed( 882e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian TargetPDecl->getDeclName().getAsIdentifierInfo())) { 883e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian DropIt = true; 884e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian break; 885e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian } 886e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian } 887e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian if (!DropIt) 888e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian MinimalConformingProtocols.push_back(TargetPDecl); 889e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian } 890651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (MinimalConformingProtocols.empty()) 891651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return; 8928c355831ac3c9e8c12b23ca69b7587dcbd0439efFariborz Jahanian edit::Commit commit(*Editor); 89344b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian rewriteToObjCInterfaceDecl(IDecl, MinimalConformingProtocols, 89444b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian *NSAPIObj, commit); 8958c355831ac3c9e8c12b23ca69b7587dcbd0439efFariborz Jahanian Editor->commit(commit); 8967556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian} 8977556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian 898b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanianvoid ObjCMigrateASTConsumer::CacheObjCNSIntegerTypedefed( 899b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian const TypedefDecl *TypedefDcl) { 900b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian 901b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian QualType qt = TypedefDcl->getTypeSourceInfo()->getType(); 902b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian if (NSAPIObj->isObjCNSIntegerType(qt)) 903b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian NSIntegerTypedefed = TypedefDcl; 904b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian else if (NSAPIObj->isObjCNSUIntegerType(qt)) 905b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian NSUIntegerTypedefed = TypedefDcl; 906b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian} 907b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian 908d2dab64a438b7b8d57f8a10883e107d2bc0988edFariborz Jahanianbool ObjCMigrateASTConsumer::migrateNSEnumDecl(ASTContext &Ctx, 909bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian const EnumDecl *EnumDcl, 910bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian const TypedefDecl *TypedefDcl) { 911bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian if (!EnumDcl->isCompleteDefinition() || EnumDcl->getIdentifier() || 9120e2c34f92f00628d48968dfea096d36381f494cbStephen Hines EnumDcl->isDeprecated()) 913b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian return false; 914b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian if (!TypedefDcl) { 915b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian if (NSIntegerTypedefed) { 916b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian TypedefDcl = NSIntegerTypedefed; 9176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines NSIntegerTypedefed = nullptr; 918b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian } 919b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian else if (NSUIntegerTypedefed) { 920b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian TypedefDcl = NSUIntegerTypedefed; 9216bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines NSUIntegerTypedefed = nullptr; 922b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian } 923b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian else 924b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian return false; 925e909a720149ba5025209096fb9ed17e0162c8873Argyrios Kyrtzidis FileID FileIdOfTypedefDcl = 926e909a720149ba5025209096fb9ed17e0162c8873Argyrios Kyrtzidis PP.getSourceManager().getFileID(TypedefDcl->getLocation()); 927e909a720149ba5025209096fb9ed17e0162c8873Argyrios Kyrtzidis FileID FileIdOfEnumDcl = 928e909a720149ba5025209096fb9ed17e0162c8873Argyrios Kyrtzidis PP.getSourceManager().getFileID(EnumDcl->getLocation()); 929b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian if (FileIdOfTypedefDcl != FileIdOfEnumDcl) 930b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian return false; 931b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian } 932b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian if (TypedefDcl->isDeprecated()) 933d2dab64a438b7b8d57f8a10883e107d2bc0988edFariborz Jahanian return false; 934bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian 935bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian QualType qt = TypedefDcl->getTypeSourceInfo()->getType(); 936176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines StringRef NSIntegerName = NSAPIObj->GetNSIntegralKind(qt); 937e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian 938176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (NSIntegerName.empty()) { 939faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian // Also check for typedef enum {...} TD; 940faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian if (const EnumType *EnumTy = qt->getAs<EnumType>()) { 941faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian if (EnumTy->getDecl() == EnumDcl) { 942ad162e912db93be9494ba3ebc12994e51e0b0db2Fariborz Jahanian bool NSOptions = UseNSOptionsMacro(PP, Ctx, EnumDcl); 943176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (!InsertFoundation(Ctx, TypedefDcl->getLocStart())) 944d2dab64a438b7b8d57f8a10883e107d2bc0988edFariborz Jahanian return false; 945faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian edit::Commit commit(*Editor); 9460e2c34f92f00628d48968dfea096d36381f494cbStephen Hines rewriteToNSMacroDecl(Ctx, EnumDcl, TypedefDcl, *NSAPIObj, commit, !NSOptions); 947faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian Editor->commit(commit); 948f98f12f5f565a914d8996d881f53253f95a2db00Fariborz Jahanian return true; 949faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian } 950faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian } 951d2dab64a438b7b8d57f8a10883e107d2bc0988edFariborz Jahanian return false; 952e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian } 953bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian 954c9820ebfeff30598ebd7369c5daf5bde10df934bFariborz Jahanian // We may still use NS_OPTIONS based on what we find in the enumertor list. 955c9820ebfeff30598ebd7369c5daf5bde10df934bFariborz Jahanian bool NSOptions = UseNSOptionsMacro(PP, Ctx, EnumDcl); 956176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (!InsertFoundation(Ctx, TypedefDcl->getLocStart())) 957d2dab64a438b7b8d57f8a10883e107d2bc0988edFariborz Jahanian return false; 958bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian edit::Commit commit(*Editor); 959b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian bool Res = rewriteToNSEnumDecl(EnumDcl, TypedefDcl, *NSAPIObj, 960176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines commit, NSIntegerName, NSOptions); 961bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian Editor->commit(commit); 962b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian return Res; 963bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian} 964bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian 9656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesstatic void ReplaceWithInstancetype(ASTContext &Ctx, 9666bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const ObjCMigrateASTConsumer &ASTC, 967f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian ObjCMethodDecl *OM) { 9686bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (OM->getReturnType() == Ctx.getObjCInstanceType()) 9696bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return; // already has instancetype. 9706bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 971f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian SourceRange R; 972f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian std::string ClassString; 973651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (TypeSourceInfo *TSInfo = OM->getReturnTypeSourceInfo()) { 974f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian TypeLoc TL = TSInfo->getTypeLoc(); 975f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian R = SourceRange(TL.getBeginLoc(), TL.getEndLoc()); 976f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian ClassString = "instancetype"; 977f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian } 978f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian else { 979f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian R = SourceRange(OM->getLocStart(), OM->getLocStart()); 980f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian ClassString = OM->isInstanceMethod() ? '-' : '+'; 981f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian ClassString += " (instancetype)"; 982f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian } 983f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian edit::Commit commit(*ASTC.Editor); 984f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian commit.replace(R, ClassString); 985f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian ASTC.Editor->commit(commit); 986f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian} 987f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian 9889fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanianstatic void ReplaceWithClasstype(const ObjCMigrateASTConsumer &ASTC, 9899fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian ObjCMethodDecl *OM) { 9909fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian ObjCInterfaceDecl *IDecl = OM->getClassInterface(); 9919fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian SourceRange R; 9929fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian std::string ClassString; 993651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (TypeSourceInfo *TSInfo = OM->getReturnTypeSourceInfo()) { 9949fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian TypeLoc TL = TSInfo->getTypeLoc(); 9959fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian R = SourceRange(TL.getBeginLoc(), TL.getEndLoc()); { 9969fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian ClassString = IDecl->getName(); 9979fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian ClassString += "*"; 9989fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian } 9999fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian } 10009fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian else { 10019fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian R = SourceRange(OM->getLocStart(), OM->getLocStart()); 10029fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian ClassString = "+ ("; 10039fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian ClassString += IDecl->getName(); ClassString += "*)"; 10049fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian } 10059fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian edit::Commit commit(*ASTC.Editor); 10069fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian commit.replace(R, ClassString); 10079fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian ASTC.Editor->commit(commit); 10089fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian} 10099fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian 101026cf046ff3a2d24ff3e2c3757599976b644a06daFariborz Jahanianvoid ObjCMigrateASTConsumer::migrateMethodInstanceType(ASTContext &Ctx, 101126cf046ff3a2d24ff3e2c3757599976b644a06daFariborz Jahanian ObjCContainerDecl *CDecl, 101226cf046ff3a2d24ff3e2c3757599976b644a06daFariborz Jahanian ObjCMethodDecl *OM) { 101311638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian ObjCInstanceTypeFamily OIT_Family = 101411638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian Selector::getInstTypeMethodFamily(OM->getSelector()); 10158d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian 101665f1a4c931bc17e51c751a5e9c6a71a9e52d5b8cFariborz Jahanian std::string ClassName; 1017211b4a2b2260ba5a3150f2b8d47f569e9773b1d3Fariborz Jahanian switch (OIT_Family) { 10188d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian case OIT_None: 10198d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian migrateFactoryMethod(Ctx, CDecl, OM); 10208d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian return; 10213c6e5ce3776eaddaf4bcdf5da6c00ec4e6829d83Fariborz Jahanian case OIT_Array: 10223c6e5ce3776eaddaf4bcdf5da6c00ec4e6829d83Fariborz Jahanian ClassName = "NSArray"; 10233c6e5ce3776eaddaf4bcdf5da6c00ec4e6829d83Fariborz Jahanian break; 10243c6e5ce3776eaddaf4bcdf5da6c00ec4e6829d83Fariborz Jahanian case OIT_Dictionary: 10253c6e5ce3776eaddaf4bcdf5da6c00ec4e6829d83Fariborz Jahanian ClassName = "NSDictionary"; 10263c6e5ce3776eaddaf4bcdf5da6c00ec4e6829d83Fariborz Jahanian break; 10278d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian case OIT_Singleton: 10288d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian migrateFactoryMethod(Ctx, CDecl, OM, OIT_Singleton); 1029211b4a2b2260ba5a3150f2b8d47f569e9773b1d3Fariborz Jahanian return; 1030a346eb1188419d3f1698092edfbd66890b74163cFariborz Jahanian case OIT_Init: 1031651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (OM->getReturnType()->isObjCIdType()) 10326bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ReplaceWithInstancetype(Ctx, *this, OM); 1033a346eb1188419d3f1698092edfbd66890b74163cFariborz Jahanian return; 10349fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian case OIT_ReturnsSelf: 10359fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian migrateFactoryMethod(Ctx, CDecl, OM, OIT_ReturnsSelf); 10369fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian return; 1037211b4a2b2260ba5a3150f2b8d47f569e9773b1d3Fariborz Jahanian } 1038651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!OM->getReturnType()->isObjCIdType()) 103911638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian return; 104011638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian 104111638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl); 104211638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian if (!IDecl) { 104311638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) 104411638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian IDecl = CatDecl->getClassInterface(); 104511638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian else if (ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(CDecl)) 104611638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian IDecl = ImpDecl->getClassInterface(); 104711638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian } 104865f1a4c931bc17e51c751a5e9c6a71a9e52d5b8cFariborz Jahanian if (!IDecl || 1049f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian !IDecl->lookupInheritedClass(&Ctx.Idents.get(ClassName))) { 1050f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian migrateFactoryMethod(Ctx, CDecl, OM); 105111638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian return; 1052cd683986e991f0e60afd6bc6f336cfc1fd844193Rafael Espindola } 10536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ReplaceWithInstancetype(Ctx, *this, OM); 105411638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian} 105511638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian 10568a6ad2a21dcb654db25cf66408466d2e7a93e09cFariborz Jahanianstatic bool TypeIsInnerPointer(QualType T) { 10578a6ad2a21dcb654db25cf66408466d2e7a93e09cFariborz Jahanian if (!T->isAnyPointerType()) 10588a6ad2a21dcb654db25cf66408466d2e7a93e09cFariborz Jahanian return false; 10598a6ad2a21dcb654db25cf66408466d2e7a93e09cFariborz Jahanian if (T->isObjCObjectPointerType() || T->isObjCBuiltinType() || 10600d4e06872de210a9f9ed89781ba606ea22fb61b8Fariborz Jahanian T->isBlockPointerType() || T->isFunctionPointerType() || 10610d4e06872de210a9f9ed89781ba606ea22fb61b8Fariborz Jahanian ento::coreFoundation::isCFObjectRef(T)) 10628a6ad2a21dcb654db25cf66408466d2e7a93e09cFariborz Jahanian return false; 1063c72b4b396a9b87cf9cdb9958308d82fd32bdb846Fariborz Jahanian // Also, typedef-of-pointer-to-incomplete-struct is something that we assume 1064c72b4b396a9b87cf9cdb9958308d82fd32bdb846Fariborz Jahanian // is not an innter pointer type. 1065c72b4b396a9b87cf9cdb9958308d82fd32bdb846Fariborz Jahanian QualType OrigT = T; 1066c72b4b396a9b87cf9cdb9958308d82fd32bdb846Fariborz Jahanian while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr())) 1067c72b4b396a9b87cf9cdb9958308d82fd32bdb846Fariborz Jahanian T = TD->getDecl()->getUnderlyingType(); 1068c72b4b396a9b87cf9cdb9958308d82fd32bdb846Fariborz Jahanian if (OrigT == T || !T->isPointerType()) 1069c72b4b396a9b87cf9cdb9958308d82fd32bdb846Fariborz Jahanian return true; 1070c72b4b396a9b87cf9cdb9958308d82fd32bdb846Fariborz Jahanian const PointerType* PT = T->getAs<PointerType>(); 1071c72b4b396a9b87cf9cdb9958308d82fd32bdb846Fariborz Jahanian QualType UPointeeT = PT->getPointeeType().getUnqualifiedType(); 1072c72b4b396a9b87cf9cdb9958308d82fd32bdb846Fariborz Jahanian if (UPointeeT->isRecordType()) { 1073c72b4b396a9b87cf9cdb9958308d82fd32bdb846Fariborz Jahanian const RecordType *RecordTy = UPointeeT->getAs<RecordType>(); 1074c72b4b396a9b87cf9cdb9958308d82fd32bdb846Fariborz Jahanian if (!RecordTy->getDecl()->isCompleteDefinition()) 1075c72b4b396a9b87cf9cdb9958308d82fd32bdb846Fariborz Jahanian return false; 1076c72b4b396a9b87cf9cdb9958308d82fd32bdb846Fariborz Jahanian } 10778a6ad2a21dcb654db25cf66408466d2e7a93e09cFariborz Jahanian return true; 10788a6ad2a21dcb654db25cf66408466d2e7a93e09cFariborz Jahanian} 10798a6ad2a21dcb654db25cf66408466d2e7a93e09cFariborz Jahanian 1080257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian/// \brief Check whether the two versions match. 1081257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanianstatic bool versionsMatch(const VersionTuple &X, const VersionTuple &Y) { 1082257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian return (X == Y); 1083257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian} 1084257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian 1085257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian/// AvailabilityAttrsMatch - This routine checks that if comparing two 1086257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian/// availability attributes, all their components match. It returns 1087257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian/// true, if not dealing with availability or when all components of 1088257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian/// availability attributes match. This routine is only called when 1089257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian/// the attributes are of the same kind. 1090257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanianstatic bool AvailabilityAttrsMatch(Attr *At1, Attr *At2) { 1091257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian const AvailabilityAttr *AA1 = dyn_cast<AvailabilityAttr>(At1); 1092257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian if (!AA1) 1093f9d38c08bc77da4ebd67fdc7cb4f42da671f7d2bFariborz Jahanian return true; 1094257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian const AvailabilityAttr *AA2 = dyn_cast<AvailabilityAttr>(At2); 1095f9d38c08bc77da4ebd67fdc7cb4f42da671f7d2bFariborz Jahanian 1096257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian VersionTuple Introduced1 = AA1->getIntroduced(); 1097257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian VersionTuple Deprecated1 = AA1->getDeprecated(); 1098257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian VersionTuple Obsoleted1 = AA1->getObsoleted(); 1099257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian bool IsUnavailable1 = AA1->getUnavailable(); 1100257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian VersionTuple Introduced2 = AA2->getIntroduced(); 1101257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian VersionTuple Deprecated2 = AA2->getDeprecated(); 1102257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian VersionTuple Obsoleted2 = AA2->getObsoleted(); 1103257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian bool IsUnavailable2 = AA2->getUnavailable(); 1104257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian return (versionsMatch(Introduced1, Introduced2) && 1105257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian versionsMatch(Deprecated1, Deprecated2) && 1106257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian versionsMatch(Obsoleted1, Obsoleted2) && 1107257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian IsUnavailable1 == IsUnavailable2); 1108257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian} 1109257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian 1110257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanianstatic bool MatchTwoAttributeLists(const AttrVec &Attrs1, const AttrVec &Attrs2, 1111257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian bool &AvailabilityArgsMatch) { 1112f9d38c08bc77da4ebd67fdc7cb4f42da671f7d2bFariborz Jahanian // This list is very small, so this need not be optimized. 1113f9d38c08bc77da4ebd67fdc7cb4f42da671f7d2bFariborz Jahanian for (unsigned i = 0, e = Attrs1.size(); i != e; i++) { 1114f9d38c08bc77da4ebd67fdc7cb4f42da671f7d2bFariborz Jahanian bool match = false; 1115f9d38c08bc77da4ebd67fdc7cb4f42da671f7d2bFariborz Jahanian for (unsigned j = 0, f = Attrs2.size(); j != f; j++) { 1116257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian // Matching attribute kind only. Except for Availabilty attributes, 1117257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian // we are not getting into details of the attributes. For all practical purposes 1118f9d38c08bc77da4ebd67fdc7cb4f42da671f7d2bFariborz Jahanian // this is sufficient. 1119f9d38c08bc77da4ebd67fdc7cb4f42da671f7d2bFariborz Jahanian if (Attrs1[i]->getKind() == Attrs2[j]->getKind()) { 1120257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian if (AvailabilityArgsMatch) 1121257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian AvailabilityArgsMatch = AvailabilityAttrsMatch(Attrs1[i], Attrs2[j]); 1122f9d38c08bc77da4ebd67fdc7cb4f42da671f7d2bFariborz Jahanian match = true; 1123f9d38c08bc77da4ebd67fdc7cb4f42da671f7d2bFariborz Jahanian break; 1124f9d38c08bc77da4ebd67fdc7cb4f42da671f7d2bFariborz Jahanian } 1125f9d38c08bc77da4ebd67fdc7cb4f42da671f7d2bFariborz Jahanian } 1126f9d38c08bc77da4ebd67fdc7cb4f42da671f7d2bFariborz Jahanian if (!match) 1127f9d38c08bc77da4ebd67fdc7cb4f42da671f7d2bFariborz Jahanian return false; 1128f9d38c08bc77da4ebd67fdc7cb4f42da671f7d2bFariborz Jahanian } 1129f9d38c08bc77da4ebd67fdc7cb4f42da671f7d2bFariborz Jahanian return true; 1130f9d38c08bc77da4ebd67fdc7cb4f42da671f7d2bFariborz Jahanian} 1131f9d38c08bc77da4ebd67fdc7cb4f42da671f7d2bFariborz Jahanian 1132257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian/// AttributesMatch - This routine checks list of attributes for two 1133257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian/// decls. It returns false, if there is a mismatch in kind of 1134257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian/// attributes seen in the decls. It returns true if the two decls 1135257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian/// have list of same kind of attributes. Furthermore, when there 1136257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian/// are availability attributes in the two decls, it sets the 1137257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian/// AvailabilityArgsMatch to false if availability attributes have 1138257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian/// different versions, etc. 1139257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanianstatic bool AttributesMatch(const Decl *Decl1, const Decl *Decl2, 1140257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian bool &AvailabilityArgsMatch) { 1141257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian if (!Decl1->hasAttrs() || !Decl2->hasAttrs()) { 1142257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian AvailabilityArgsMatch = (Decl1->hasAttrs() == Decl2->hasAttrs()); 1143257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian return true; 1144257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian } 1145257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian AvailabilityArgsMatch = true; 1146257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian const AttrVec &Attrs1 = Decl1->getAttrs(); 1147257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian const AttrVec &Attrs2 = Decl2->getAttrs(); 1148257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian bool match = MatchTwoAttributeLists(Attrs1, Attrs2, AvailabilityArgsMatch); 1149257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian if (match && (Attrs2.size() > Attrs1.size())) 1150257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian return MatchTwoAttributeLists(Attrs2, Attrs1, AvailabilityArgsMatch); 1151257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian return match; 1152257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian} 1153257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian 11549fd802448d463777ed87d56a196b84da1ccdeaa5Fariborz Jahanianstatic bool IsValidIdentifier(ASTContext &Ctx, 11559fd802448d463777ed87d56a196b84da1ccdeaa5Fariborz Jahanian const char *Name) { 11569fd802448d463777ed87d56a196b84da1ccdeaa5Fariborz Jahanian if (!isIdentifierHead(Name[0])) 11579fd802448d463777ed87d56a196b84da1ccdeaa5Fariborz Jahanian return false; 11589fd802448d463777ed87d56a196b84da1ccdeaa5Fariborz Jahanian std::string NameString = Name; 11599fd802448d463777ed87d56a196b84da1ccdeaa5Fariborz Jahanian NameString[0] = toLowercase(NameString[0]); 11609fd802448d463777ed87d56a196b84da1ccdeaa5Fariborz Jahanian IdentifierInfo *II = &Ctx.Idents.get(NameString); 11619fd802448d463777ed87d56a196b84da1ccdeaa5Fariborz Jahanian return II->getTokenID() == tok::identifier; 11629fd802448d463777ed87d56a196b84da1ccdeaa5Fariborz Jahanian} 11639fd802448d463777ed87d56a196b84da1ccdeaa5Fariborz Jahanian 11648451a458d65879bb594ee879353658723feda0eeFariborz Jahanianbool ObjCMigrateASTConsumer::migrateProperty(ASTContext &Ctx, 11659c4759149c80464ca26dcc90c756f439e6640684Fariborz Jahanian ObjCContainerDecl *D, 11668451a458d65879bb594ee879353658723feda0eeFariborz Jahanian ObjCMethodDecl *Method) { 11678451a458d65879bb594ee879353658723feda0eeFariborz Jahanian if (Method->isPropertyAccessor() || !Method->isInstanceMethod() || 11688451a458d65879bb594ee879353658723feda0eeFariborz Jahanian Method->param_size() != 0) 11698451a458d65879bb594ee879353658723feda0eeFariborz Jahanian return false; 11708451a458d65879bb594ee879353658723feda0eeFariborz Jahanian // Is this method candidate to be a getter? 1171651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines QualType GRT = Method->getReturnType(); 11728451a458d65879bb594ee879353658723feda0eeFariborz Jahanian if (GRT->isVoidType()) 11738451a458d65879bb594ee879353658723feda0eeFariborz Jahanian return false; 11748451a458d65879bb594ee879353658723feda0eeFariborz Jahanian 11758451a458d65879bb594ee879353658723feda0eeFariborz Jahanian Selector GetterSelector = Method->getSelector(); 1176641649faa2a96dc5a2bbfcb9447b680fbedff962Fariborz Jahanian ObjCInstanceTypeFamily OIT_Family = 1177641649faa2a96dc5a2bbfcb9447b680fbedff962Fariborz Jahanian Selector::getInstTypeMethodFamily(GetterSelector); 1178641649faa2a96dc5a2bbfcb9447b680fbedff962Fariborz Jahanian 1179641649faa2a96dc5a2bbfcb9447b680fbedff962Fariborz Jahanian if (OIT_Family != OIT_None) 1180641649faa2a96dc5a2bbfcb9447b680fbedff962Fariborz Jahanian return false; 1181641649faa2a96dc5a2bbfcb9447b680fbedff962Fariborz Jahanian 11828451a458d65879bb594ee879353658723feda0eeFariborz Jahanian IdentifierInfo *getterName = GetterSelector.getIdentifierInfoForSlot(0); 11838451a458d65879bb594ee879353658723feda0eeFariborz Jahanian Selector SetterSelector = 11848451a458d65879bb594ee879353658723feda0eeFariborz Jahanian SelectorTable::constructSetterSelector(PP.getIdentifierTable(), 11858451a458d65879bb594ee879353658723feda0eeFariborz Jahanian PP.getSelectorTable(), 11868451a458d65879bb594ee879353658723feda0eeFariborz Jahanian getterName); 11879c4759149c80464ca26dcc90c756f439e6640684Fariborz Jahanian ObjCMethodDecl *SetterMethod = D->getInstanceMethod(SetterSelector); 1188a81f102bd396fd1da61b47337a2389f352baf539Fariborz Jahanian unsigned LengthOfPrefix = 0; 11898451a458d65879bb594ee879353658723feda0eeFariborz Jahanian if (!SetterMethod) { 11908451a458d65879bb594ee879353658723feda0eeFariborz Jahanian // try a different naming convention for getter: isXxxxx 11918451a458d65879bb594ee879353658723feda0eeFariborz Jahanian StringRef getterNameString = getterName->getName(); 1192a81f102bd396fd1da61b47337a2389f352baf539Fariborz Jahanian bool IsPrefix = getterNameString.startswith("is"); 119389ac7412ea3137f22065985c562a3050130e6ca0Fariborz Jahanian // Note that we don't want to change an isXXX method of retainable object 119489ac7412ea3137f22065985c562a3050130e6ca0Fariborz Jahanian // type to property (readonly or otherwise). 119589ac7412ea3137f22065985c562a3050130e6ca0Fariborz Jahanian if (IsPrefix && GRT->isObjCRetainableType()) 119689ac7412ea3137f22065985c562a3050130e6ca0Fariborz Jahanian return false; 119789ac7412ea3137f22065985c562a3050130e6ca0Fariborz Jahanian if (IsPrefix || getterNameString.startswith("get")) { 1198a81f102bd396fd1da61b47337a2389f352baf539Fariborz Jahanian LengthOfPrefix = (IsPrefix ? 2 : 3); 1199a81f102bd396fd1da61b47337a2389f352baf539Fariborz Jahanian const char *CGetterName = getterNameString.data() + LengthOfPrefix; 1200a81f102bd396fd1da61b47337a2389f352baf539Fariborz Jahanian // Make sure that first character after "is" or "get" prefix can 1201a81f102bd396fd1da61b47337a2389f352baf539Fariborz Jahanian // start an identifier. 12029fd802448d463777ed87d56a196b84da1ccdeaa5Fariborz Jahanian if (!IsValidIdentifier(Ctx, CGetterName)) 1203a81f102bd396fd1da61b47337a2389f352baf539Fariborz Jahanian return false; 12048451a458d65879bb594ee879353658723feda0eeFariborz Jahanian if (CGetterName[0] && isUppercase(CGetterName[0])) { 12058451a458d65879bb594ee879353658723feda0eeFariborz Jahanian getterName = &Ctx.Idents.get(CGetterName); 12068451a458d65879bb594ee879353658723feda0eeFariborz Jahanian SetterSelector = 12078451a458d65879bb594ee879353658723feda0eeFariborz Jahanian SelectorTable::constructSetterSelector(PP.getIdentifierTable(), 12088451a458d65879bb594ee879353658723feda0eeFariborz Jahanian PP.getSelectorTable(), 12098451a458d65879bb594ee879353658723feda0eeFariborz Jahanian getterName); 12109c4759149c80464ca26dcc90c756f439e6640684Fariborz Jahanian SetterMethod = D->getInstanceMethod(SetterSelector); 12118451a458d65879bb594ee879353658723feda0eeFariborz Jahanian } 12128451a458d65879bb594ee879353658723feda0eeFariborz Jahanian } 12138451a458d65879bb594ee879353658723feda0eeFariborz Jahanian } 121489ac7412ea3137f22065985c562a3050130e6ca0Fariborz Jahanian 12158451a458d65879bb594ee879353658723feda0eeFariborz Jahanian if (SetterMethod) { 1216081099d302b79d1746c7a39da14e3265971eb718Fariborz Jahanian if ((ASTMigrateActions & FrontendOptions::ObjCMT_ReadwriteProperty) == 0) 1217081099d302b79d1746c7a39da14e3265971eb718Fariborz Jahanian return false; 1218257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian bool AvailabilityArgsMatch; 1219f9d38c08bc77da4ebd67fdc7cb4f42da671f7d2bFariborz Jahanian if (SetterMethod->isDeprecated() || 1220257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian !AttributesMatch(Method, SetterMethod, AvailabilityArgsMatch)) 12219a65f4251fe5548e0b4478d584796ca84a6f5ebcFariborz Jahanian return false; 1222f9d38c08bc77da4ebd67fdc7cb4f42da671f7d2bFariborz Jahanian 12238451a458d65879bb594ee879353658723feda0eeFariborz Jahanian // Is this a valid setter, matching the target getter? 1224651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines QualType SRT = SetterMethod->getReturnType(); 12258451a458d65879bb594ee879353658723feda0eeFariborz Jahanian if (!SRT->isVoidType()) 12268451a458d65879bb594ee879353658723feda0eeFariborz Jahanian return false; 12278451a458d65879bb594ee879353658723feda0eeFariborz Jahanian const ParmVarDecl *argDecl = *SetterMethod->param_begin(); 12288451a458d65879bb594ee879353658723feda0eeFariborz Jahanian QualType ArgType = argDecl->getType(); 1229f9d38c08bc77da4ebd67fdc7cb4f42da671f7d2bFariborz Jahanian if (!Ctx.hasSameUnqualifiedType(ArgType, GRT)) 12308451a458d65879bb594ee879353658723feda0eeFariborz Jahanian return false; 12318451a458d65879bb594ee879353658723feda0eeFariborz Jahanian edit::Commit commit(*Editor); 12328451a458d65879bb594ee879353658723feda0eeFariborz Jahanian rewriteToObjCProperty(Method, SetterMethod, *NSAPIObj, commit, 123339ebb02cb0bd342ced56de6d19aa9992aa0371b8Fariborz Jahanian LengthOfPrefix, 123439ebb02cb0bd342ced56de6d19aa9992aa0371b8Fariborz Jahanian (ASTMigrateActions & 1235257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian FrontendOptions::ObjCMT_AtomicProperty) != 0, 12365d2a20671954f55f765b96375e8bcd38367cb3baFariborz Jahanian (ASTMigrateActions & 12375d2a20671954f55f765b96375e8bcd38367cb3baFariborz Jahanian FrontendOptions::ObjCMT_NsAtomicIOSOnlyProperty) != 0, 1238257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian AvailabilityArgsMatch); 12398451a458d65879bb594ee879353658723feda0eeFariborz Jahanian Editor->commit(commit); 12408451a458d65879bb594ee879353658723feda0eeFariborz Jahanian return true; 12418451a458d65879bb594ee879353658723feda0eeFariborz Jahanian } 124274fd551c0ba344d62aedc8636ed81b45652f04d8Fariborz Jahanian else if (ASTMigrateActions & FrontendOptions::ObjCMT_ReadonlyProperty) { 12438451a458d65879bb594ee879353658723feda0eeFariborz Jahanian // Try a non-void method with no argument (and no setter or property of same name 12448451a458d65879bb594ee879353658723feda0eeFariborz Jahanian // as a 'readonly' property. 12458451a458d65879bb594ee879353658723feda0eeFariborz Jahanian edit::Commit commit(*Editor); 12466bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines rewriteToObjCProperty(Method, nullptr /*SetterMethod*/, *NSAPIObj, commit, 124739ebb02cb0bd342ced56de6d19aa9992aa0371b8Fariborz Jahanian LengthOfPrefix, 124839ebb02cb0bd342ced56de6d19aa9992aa0371b8Fariborz Jahanian (ASTMigrateActions & 1249257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian FrontendOptions::ObjCMT_AtomicProperty) != 0, 12505d2a20671954f55f765b96375e8bcd38367cb3baFariborz Jahanian (ASTMigrateActions & 12515d2a20671954f55f765b96375e8bcd38367cb3baFariborz Jahanian FrontendOptions::ObjCMT_NsAtomicIOSOnlyProperty) != 0, 1252257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian /*AvailabilityArgsMatch*/false); 12538451a458d65879bb594ee879353658723feda0eeFariborz Jahanian Editor->commit(commit); 12548451a458d65879bb594ee879353658723feda0eeFariborz Jahanian return true; 12558451a458d65879bb594ee879353658723feda0eeFariborz Jahanian } 12568451a458d65879bb594ee879353658723feda0eeFariborz Jahanian return false; 12578451a458d65879bb594ee879353658723feda0eeFariborz Jahanian} 12588451a458d65879bb594ee879353658723feda0eeFariborz Jahanian 12598a6ad2a21dcb654db25cf66408466d2e7a93e09cFariborz Jahanianvoid ObjCMigrateASTConsumer::migrateNsReturnsInnerPointer(ASTContext &Ctx, 12608a6ad2a21dcb654db25cf66408466d2e7a93e09cFariborz Jahanian ObjCMethodDecl *OM) { 1261f85f5e4769730e06590d969ad3cbff879d8006f6Fariborz Jahanian if (OM->isImplicit() || 1262f1ebccd82bbef0547fe1a8d14d2e74e7570be8abFariborz Jahanian !OM->isInstanceMethod() || 1263f85f5e4769730e06590d969ad3cbff879d8006f6Fariborz Jahanian OM->hasAttr<ObjCReturnsInnerPointerAttr>()) 12648a6ad2a21dcb654db25cf66408466d2e7a93e09cFariborz Jahanian return; 1265651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1266651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines QualType RT = OM->getReturnType(); 12678a6ad2a21dcb654db25cf66408466d2e7a93e09cFariborz Jahanian if (!TypeIsInnerPointer(RT) || 1268b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar !NSAPIObj->isMacroDefined("NS_RETURNS_INNER_POINTER")) 12698a6ad2a21dcb654db25cf66408466d2e7a93e09cFariborz Jahanian return; 12708a6ad2a21dcb654db25cf66408466d2e7a93e09cFariborz Jahanian 12718a6ad2a21dcb654db25cf66408466d2e7a93e09cFariborz Jahanian edit::Commit commit(*Editor); 12728a6ad2a21dcb654db25cf66408466d2e7a93e09cFariborz Jahanian commit.insertBefore(OM->getLocEnd(), " NS_RETURNS_INNER_POINTER"); 12738a6ad2a21dcb654db25cf66408466d2e7a93e09cFariborz Jahanian Editor->commit(commit); 12748a6ad2a21dcb654db25cf66408466d2e7a93e09cFariborz Jahanian} 12758a6ad2a21dcb654db25cf66408466d2e7a93e09cFariborz Jahanian 1276f85f5e4769730e06590d969ad3cbff879d8006f6Fariborz Jahanianvoid ObjCMigrateASTConsumer::migratePropertyNsReturnsInnerPointer(ASTContext &Ctx, 1277f85f5e4769730e06590d969ad3cbff879d8006f6Fariborz Jahanian ObjCPropertyDecl *P) { 1278f85f5e4769730e06590d969ad3cbff879d8006f6Fariborz Jahanian QualType T = P->getType(); 1279b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar 1280f85f5e4769730e06590d969ad3cbff879d8006f6Fariborz Jahanian if (!TypeIsInnerPointer(T) || 1281b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar !NSAPIObj->isMacroDefined("NS_RETURNS_INNER_POINTER")) 1282f85f5e4769730e06590d969ad3cbff879d8006f6Fariborz Jahanian return; 1283f85f5e4769730e06590d969ad3cbff879d8006f6Fariborz Jahanian edit::Commit commit(*Editor); 1284f85f5e4769730e06590d969ad3cbff879d8006f6Fariborz Jahanian commit.insertBefore(P->getLocEnd(), " NS_RETURNS_INNER_POINTER "); 1285f85f5e4769730e06590d969ad3cbff879d8006f6Fariborz Jahanian Editor->commit(commit); 1286f85f5e4769730e06590d969ad3cbff879d8006f6Fariborz Jahanian} 1287f85f5e4769730e06590d969ad3cbff879d8006f6Fariborz Jahanian 1288b8941a15b6b5477a81c189614d0129070ac099f1Fariborz Jahanianvoid ObjCMigrateASTConsumer::migrateAllMethodInstaceType(ASTContext &Ctx, 128911638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian ObjCContainerDecl *CDecl) { 1290651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (CDecl->isDeprecated() || IsCategoryNameWithDeprecatedSuffix(CDecl)) 12914667154c4cd7724f751c1c72af0ee05bcf5908daFariborz Jahanian return; 12924667154c4cd7724f751c1c72af0ee05bcf5908daFariborz Jahanian 129311638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian // migrate methods which can have instancetype as their result type. 1294651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto *Method : CDecl->methods()) { 1295641645f00c22e1f55794537a43646214402e99a1Fariborz Jahanian if (Method->isDeprecated()) 1296641645f00c22e1f55794537a43646214402e99a1Fariborz Jahanian continue; 129711638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian migrateMethodInstanceType(Ctx, CDecl, Method); 129811638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian } 129911638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian} 130011638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian 1301f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanianvoid ObjCMigrateASTConsumer::migrateFactoryMethod(ASTContext &Ctx, 1302f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian ObjCContainerDecl *CDecl, 13038d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian ObjCMethodDecl *OM, 13048d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian ObjCInstanceTypeFamily OIT_Family) { 1305c217ced5ada5c5723bfca450b37ac046193a8c2fFariborz Jahanian if (OM->isInstanceMethod() || 1306651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OM->getReturnType() == Ctx.getObjCInstanceType() || 1307651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines !OM->getReturnType()->isObjCIdType()) 1308f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian return; 1309f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian 1310f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian // Candidate factory methods are + (id) NaMeXXX : ... which belong to a class 1311f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian // NSYYYNamE with matching names be at least 3 characters long. 1312f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl); 1313f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian if (!IDecl) { 1314f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) 1315f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian IDecl = CatDecl->getClassInterface(); 1316f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian else if (ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(CDecl)) 1317f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian IDecl = ImpDecl->getClassInterface(); 1318f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian } 1319f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian if (!IDecl) 1320f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian return; 1321f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian 1322f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian std::string StringClassName = IDecl->getName(); 1323f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian StringRef LoweredClassName(StringClassName); 1324f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian std::string StringLoweredClassName = LoweredClassName.lower(); 1325f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian LoweredClassName = StringLoweredClassName; 1326f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian 1327f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian IdentifierInfo *MethodIdName = OM->getSelector().getIdentifierInfoForSlot(0); 1328086d565d2d3b8e72f95492d3a2cefd09e1718f2aFariborz Jahanian // Handle method with no name at its first selector slot; e.g. + (id):(int)x. 1329086d565d2d3b8e72f95492d3a2cefd09e1718f2aFariborz Jahanian if (!MethodIdName) 1330086d565d2d3b8e72f95492d3a2cefd09e1718f2aFariborz Jahanian return; 1331086d565d2d3b8e72f95492d3a2cefd09e1718f2aFariborz Jahanian 1332f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian std::string MethodName = MethodIdName->getName(); 13339fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian if (OIT_Family == OIT_Singleton || OIT_Family == OIT_ReturnsSelf) { 13348d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian StringRef STRefMethodName(MethodName); 13358d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian size_t len = 0; 13368d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian if (STRefMethodName.startswith("standard")) 13378d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian len = strlen("standard"); 13388d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian else if (STRefMethodName.startswith("shared")) 13398d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian len = strlen("shared"); 13408d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian else if (STRefMethodName.startswith("default")) 13418d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian len = strlen("default"); 13428d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian else 13438d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian return; 13448d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian MethodName = STRefMethodName.substr(len); 13458d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian } 1346f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian std::string MethodNameSubStr = MethodName.substr(0, 3); 1347f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian StringRef MethodNamePrefix(MethodNameSubStr); 1348f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian std::string StringLoweredMethodNamePrefix = MethodNamePrefix.lower(); 1349f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian MethodNamePrefix = StringLoweredMethodNamePrefix; 1350f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian size_t Ix = LoweredClassName.rfind(MethodNamePrefix); 1351f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian if (Ix == StringRef::npos) 1352f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian return; 1353f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian std::string ClassNamePostfix = LoweredClassName.substr(Ix); 1354f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian StringRef LoweredMethodName(MethodName); 1355f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian std::string StringLoweredMethodName = LoweredMethodName.lower(); 1356f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian LoweredMethodName = StringLoweredMethodName; 1357f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian if (!LoweredMethodName.startswith(ClassNamePostfix)) 1358f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian return; 13599fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian if (OIT_Family == OIT_ReturnsSelf) 13609fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian ReplaceWithClasstype(*this, OM); 13619fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian else 13626bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ReplaceWithInstancetype(Ctx, *this, OM); 1363f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian} 1364f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian 136557c372a674beee5054a57026de46c280df1df577Fariborz Jahanianstatic bool IsVoidStarType(QualType Ty) { 136657c372a674beee5054a57026de46c280df1df577Fariborz Jahanian if (!Ty->isPointerType()) 136757c372a674beee5054a57026de46c280df1df577Fariborz Jahanian return false; 136857c372a674beee5054a57026de46c280df1df577Fariborz Jahanian 136957c372a674beee5054a57026de46c280df1df577Fariborz Jahanian while (const TypedefType *TD = dyn_cast<TypedefType>(Ty.getTypePtr())) 137057c372a674beee5054a57026de46c280df1df577Fariborz Jahanian Ty = TD->getDecl()->getUnderlyingType(); 137157c372a674beee5054a57026de46c280df1df577Fariborz Jahanian 137257c372a674beee5054a57026de46c280df1df577Fariborz Jahanian // Is the type void*? 137357c372a674beee5054a57026de46c280df1df577Fariborz Jahanian const PointerType* PT = Ty->getAs<PointerType>(); 137457c372a674beee5054a57026de46c280df1df577Fariborz Jahanian if (PT->getPointeeType().getUnqualifiedType()->isVoidType()) 137557c372a674beee5054a57026de46c280df1df577Fariborz Jahanian return true; 137657c372a674beee5054a57026de46c280df1df577Fariborz Jahanian return IsVoidStarType(PT->getPointeeType()); 137757c372a674beee5054a57026de46c280df1df577Fariborz Jahanian} 137857c372a674beee5054a57026de46c280df1df577Fariborz Jahanian 1379a46c6c3baa0bb24987b44ac7a5543fa60e8b639eFariborz Jahanian/// AuditedType - This routine audits the type AT and returns false if it is one of known 1380a46c6c3baa0bb24987b44ac7a5543fa60e8b639eFariborz Jahanian/// CF object types or of the "void *" variety. It returns true if we don't care about the type 1381a46c6c3baa0bb24987b44ac7a5543fa60e8b639eFariborz Jahanian/// such as a non-pointer or pointers which have no ownership issues (such as "int *"). 1382a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanianstatic bool AuditedType (QualType AT) { 1383a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian if (!AT->isAnyPointerType() && !AT->isBlockPointerType()) 13846cb33a4e9e8298dfa4a8aa33ccc34ce68580f234Fariborz Jahanian return true; 13856cb33a4e9e8298dfa4a8aa33ccc34ce68580f234Fariborz Jahanian // FIXME. There isn't much we can say about CF pointer type; or is there? 1386a46c6c3baa0bb24987b44ac7a5543fa60e8b639eFariborz Jahanian if (ento::coreFoundation::isCFObjectRef(AT) || 1387a46c6c3baa0bb24987b44ac7a5543fa60e8b639eFariborz Jahanian IsVoidStarType(AT) || 1388a46c6c3baa0bb24987b44ac7a5543fa60e8b639eFariborz Jahanian // If an ObjC object is type, assuming that it is not a CF function and 1389a46c6c3baa0bb24987b44ac7a5543fa60e8b639eFariborz Jahanian // that it is an un-audited function. 1390b78b664213aae4282bee33e421ed03fdec36eb3aFariborz Jahanian AT->isObjCObjectPointerType() || AT->isObjCBuiltinType()) 13916cb33a4e9e8298dfa4a8aa33ccc34ce68580f234Fariborz Jahanian return false; 1392a46c6c3baa0bb24987b44ac7a5543fa60e8b639eFariborz Jahanian // All other pointers are assumed audited as harmless. 13936cb33a4e9e8298dfa4a8aa33ccc34ce68580f234Fariborz Jahanian return true; 139457c372a674beee5054a57026de46c280df1df577Fariborz Jahanian} 139557c372a674beee5054a57026de46c280df1df577Fariborz Jahanian 1396dead50d347e9517d80f007a93df6295f66aa0f00Fariborz Jahanianvoid ObjCMigrateASTConsumer::AnnotateImplicitBridging(ASTContext &Ctx) { 1397d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian if (CFFunctionIBCandidates.empty()) 1398d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian return; 1399b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar if (!NSAPIObj->isMacroDefined("CF_IMPLICIT_BRIDGING_ENABLED")) { 1400dead50d347e9517d80f007a93df6295f66aa0f00Fariborz Jahanian CFFunctionIBCandidates.clear(); 1401e909a720149ba5025209096fb9ed17e0162c8873Argyrios Kyrtzidis FileId = FileID(); 1402dead50d347e9517d80f007a93df6295f66aa0f00Fariborz Jahanian return; 1403dead50d347e9517d80f007a93df6295f66aa0f00Fariborz Jahanian } 1404dead50d347e9517d80f007a93df6295f66aa0f00Fariborz Jahanian // Insert CF_IMPLICIT_BRIDGING_ENABLE/CF_IMPLICIT_BRIDGING_DISABLED 1405d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian const Decl *FirstFD = CFFunctionIBCandidates[0]; 1406d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian const Decl *LastFD = 1407d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian CFFunctionIBCandidates[CFFunctionIBCandidates.size()-1]; 1408dead50d347e9517d80f007a93df6295f66aa0f00Fariborz Jahanian const char *PragmaString = "\nCF_IMPLICIT_BRIDGING_ENABLED\n\n"; 1409dead50d347e9517d80f007a93df6295f66aa0f00Fariborz Jahanian edit::Commit commit(*Editor); 1410dead50d347e9517d80f007a93df6295f66aa0f00Fariborz Jahanian commit.insertBefore(FirstFD->getLocStart(), PragmaString); 1411dead50d347e9517d80f007a93df6295f66aa0f00Fariborz Jahanian PragmaString = "\n\nCF_IMPLICIT_BRIDGING_DISABLED\n"; 1412dead50d347e9517d80f007a93df6295f66aa0f00Fariborz Jahanian SourceLocation EndLoc = LastFD->getLocEnd(); 1413dead50d347e9517d80f007a93df6295f66aa0f00Fariborz Jahanian // get location just past end of function location. 1414dead50d347e9517d80f007a93df6295f66aa0f00Fariborz Jahanian EndLoc = PP.getLocForEndOfToken(EndLoc); 1415d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian if (isa<FunctionDecl>(LastFD)) { 1416d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian // For Methods, EndLoc points to the ending semcolon. So, 1417d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian // not of these extra work is needed. 1418d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian Token Tok; 1419d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian // get locaiton of token that comes after end of function. 1420d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian bool Failed = PP.getRawToken(EndLoc, Tok, /*IgnoreWhiteSpace=*/true); 1421d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian if (!Failed) 1422d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian EndLoc = Tok.getLocation(); 1423d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian } 1424dead50d347e9517d80f007a93df6295f66aa0f00Fariborz Jahanian commit.insertAfterToken(EndLoc, PragmaString); 1425dead50d347e9517d80f007a93df6295f66aa0f00Fariborz Jahanian Editor->commit(commit); 1426e909a720149ba5025209096fb9ed17e0162c8873Argyrios Kyrtzidis FileId = FileID(); 1427dead50d347e9517d80f007a93df6295f66aa0f00Fariborz Jahanian CFFunctionIBCandidates.clear(); 1428dead50d347e9517d80f007a93df6295f66aa0f00Fariborz Jahanian} 1429dead50d347e9517d80f007a93df6295f66aa0f00Fariborz Jahanian 1430d76941102f17d5f4e88ef027151c20c95b745c8bFariborz Jahanianvoid ObjCMigrateASTConsumer::migrateCFAnnotation(ASTContext &Ctx, const Decl *Decl) { 1431641645f00c22e1f55794537a43646214402e99a1Fariborz Jahanian if (Decl->isDeprecated()) 1432641645f00c22e1f55794537a43646214402e99a1Fariborz Jahanian return; 1433641645f00c22e1f55794537a43646214402e99a1Fariborz Jahanian 1434d76941102f17d5f4e88ef027151c20c95b745c8bFariborz Jahanian if (Decl->hasAttr<CFAuditedTransferAttr>()) { 14353abb729514e871b46e0f03855fd686009f3b22b9Fariborz Jahanian assert(CFFunctionIBCandidates.empty() && 1436d76941102f17d5f4e88ef027151c20c95b745c8bFariborz Jahanian "Cannot have audited functions/methods inside user " 14373abb729514e871b46e0f03855fd686009f3b22b9Fariborz Jahanian "provided CF_IMPLICIT_BRIDGING_ENABLE"); 14383abb729514e871b46e0f03855fd686009f3b22b9Fariborz Jahanian return; 14393abb729514e871b46e0f03855fd686009f3b22b9Fariborz Jahanian } 14403abb729514e871b46e0f03855fd686009f3b22b9Fariborz Jahanian 144157c372a674beee5054a57026de46c280df1df577Fariborz Jahanian // Finction must be annotated first. 14425f7ac67c84e7b9a04fa4c5065e384f928c8f812fFariborz Jahanian if (const FunctionDecl *FuncDecl = dyn_cast<FunctionDecl>(Decl)) { 14435f7ac67c84e7b9a04fa4c5065e384f928c8f812fFariborz Jahanian CF_BRIDGING_KIND AuditKind = migrateAddFunctionAnnotation(Ctx, FuncDecl); 14445f7ac67c84e7b9a04fa4c5065e384f928c8f812fFariborz Jahanian if (AuditKind == CF_BRIDGING_ENABLE) { 1445a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian CFFunctionIBCandidates.push_back(Decl); 1446e909a720149ba5025209096fb9ed17e0162c8873Argyrios Kyrtzidis if (FileId.isInvalid()) 1447e909a720149ba5025209096fb9ed17e0162c8873Argyrios Kyrtzidis FileId = PP.getSourceManager().getFileID(Decl->getLocation()); 1448a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian } 14495f7ac67c84e7b9a04fa4c5065e384f928c8f812fFariborz Jahanian else if (AuditKind == CF_BRIDGING_MAY_INCLUDE) { 14505f7ac67c84e7b9a04fa4c5065e384f928c8f812fFariborz Jahanian if (!CFFunctionIBCandidates.empty()) { 14515f7ac67c84e7b9a04fa4c5065e384f928c8f812fFariborz Jahanian CFFunctionIBCandidates.push_back(Decl); 1452e909a720149ba5025209096fb9ed17e0162c8873Argyrios Kyrtzidis if (FileId.isInvalid()) 1453e909a720149ba5025209096fb9ed17e0162c8873Argyrios Kyrtzidis FileId = PP.getSourceManager().getFileID(Decl->getLocation()); 14545f7ac67c84e7b9a04fa4c5065e384f928c8f812fFariborz Jahanian } 14555f7ac67c84e7b9a04fa4c5065e384f928c8f812fFariborz Jahanian } 14565f7ac67c84e7b9a04fa4c5065e384f928c8f812fFariborz Jahanian else 14575f7ac67c84e7b9a04fa4c5065e384f928c8f812fFariborz Jahanian AnnotateImplicitBridging(Ctx); 1458a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian } 14595f7ac67c84e7b9a04fa4c5065e384f928c8f812fFariborz Jahanian else { 14605f7ac67c84e7b9a04fa4c5065e384f928c8f812fFariborz Jahanian migrateAddMethodAnnotation(Ctx, cast<ObjCMethodDecl>(Decl)); 1461dead50d347e9517d80f007a93df6295f66aa0f00Fariborz Jahanian AnnotateImplicitBridging(Ctx); 14625f7ac67c84e7b9a04fa4c5065e384f928c8f812fFariborz Jahanian } 146357c372a674beee5054a57026de46c280df1df577Fariborz Jahanian} 146457c372a674beee5054a57026de46c280df1df577Fariborz Jahanian 1465a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanianvoid ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx, 1466a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian const CallEffects &CE, 1467c1cc488c3cf9ce7f7b7e211e891e2be7391e0e5aFariborz Jahanian const FunctionDecl *FuncDecl, 1468c1cc488c3cf9ce7f7b7e211e891e2be7391e0e5aFariborz Jahanian bool ResultAnnotated) { 1469a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian // Annotate function. 1470c1cc488c3cf9ce7f7b7e211e891e2be7391e0e5aFariborz Jahanian if (!ResultAnnotated) { 14716cb33a4e9e8298dfa4a8aa33ccc34ce68580f234Fariborz Jahanian RetEffect Ret = CE.getReturnValue(); 14726bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const char *AnnotationString = nullptr; 14734afe57965e19d9c9ba8070ac9901ed8a20e20fceFariborz Jahanian if (Ret.getObjKind() == RetEffect::CF) { 1474b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar if (Ret.isOwned() && NSAPIObj->isMacroDefined("CF_RETURNS_RETAINED")) 14756cb33a4e9e8298dfa4a8aa33ccc34ce68580f234Fariborz Jahanian AnnotationString = " CF_RETURNS_RETAINED"; 14764afe57965e19d9c9ba8070ac9901ed8a20e20fceFariborz Jahanian else if (Ret.notOwned() && 1477b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar NSAPIObj->isMacroDefined("CF_RETURNS_NOT_RETAINED")) 14786cb33a4e9e8298dfa4a8aa33ccc34ce68580f234Fariborz Jahanian AnnotationString = " CF_RETURNS_NOT_RETAINED"; 14796cb33a4e9e8298dfa4a8aa33ccc34ce68580f234Fariborz Jahanian } 14804afe57965e19d9c9ba8070ac9901ed8a20e20fceFariborz Jahanian else if (Ret.getObjKind() == RetEffect::ObjC) { 1481b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar if (Ret.isOwned() && NSAPIObj->isMacroDefined("NS_RETURNS_RETAINED")) 14824afe57965e19d9c9ba8070ac9901ed8a20e20fceFariborz Jahanian AnnotationString = " NS_RETURNS_RETAINED"; 14834afe57965e19d9c9ba8070ac9901ed8a20e20fceFariborz Jahanian } 14844afe57965e19d9c9ba8070ac9901ed8a20e20fceFariborz Jahanian 14856cb33a4e9e8298dfa4a8aa33ccc34ce68580f234Fariborz Jahanian if (AnnotationString) { 14866cb33a4e9e8298dfa4a8aa33ccc34ce68580f234Fariborz Jahanian edit::Commit commit(*Editor); 14876cb33a4e9e8298dfa4a8aa33ccc34ce68580f234Fariborz Jahanian commit.insertAfterToken(FuncDecl->getLocEnd(), AnnotationString); 14886cb33a4e9e8298dfa4a8aa33ccc34ce68580f234Fariborz Jahanian Editor->commit(commit); 14896cb33a4e9e8298dfa4a8aa33ccc34ce68580f234Fariborz Jahanian } 1490a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian } 1491c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ArrayRef<ArgEffect> AEArgs = CE.getArgs(); 1492a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian unsigned i = 0; 1493a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian for (FunctionDecl::param_const_iterator pi = FuncDecl->param_begin(), 1494a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) { 1495a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian const ParmVarDecl *pd = *pi; 1496a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian ArgEffect AE = AEArgs[i]; 1497651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (AE == DecRef && !pd->hasAttr<CFConsumedAttr>() && 1498b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar NSAPIObj->isMacroDefined("CF_CONSUMED")) { 1499a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian edit::Commit commit(*Editor); 1500a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian commit.insertBefore(pd->getLocation(), "CF_CONSUMED "); 1501a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian Editor->commit(commit); 1502a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian } 1503651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines else if (AE == DecRefMsg && !pd->hasAttr<NSConsumedAttr>() && 1504b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar NSAPIObj->isMacroDefined("NS_CONSUMED")) { 15054afe57965e19d9c9ba8070ac9901ed8a20e20fceFariborz Jahanian edit::Commit commit(*Editor); 15064afe57965e19d9c9ba8070ac9901ed8a20e20fceFariborz Jahanian commit.insertBefore(pd->getLocation(), "NS_CONSUMED "); 15074afe57965e19d9c9ba8070ac9901ed8a20e20fceFariborz Jahanian Editor->commit(commit); 15084afe57965e19d9c9ba8070ac9901ed8a20e20fceFariborz Jahanian } 1509a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian } 1510a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian} 1511a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian 1512a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz JahanianObjCMigrateASTConsumer::CF_BRIDGING_KIND 1513a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian ObjCMigrateASTConsumer::migrateAddFunctionAnnotation( 1514a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian ASTContext &Ctx, 1515a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian const FunctionDecl *FuncDecl) { 1516a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian if (FuncDecl->hasBody()) 1517a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian return CF_BRIDGING_NONE; 1518a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian 1519a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian CallEffects CE = CallEffects::getEffect(FuncDecl); 1520651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool FuncIsReturnAnnotated = (FuncDecl->hasAttr<CFReturnsRetainedAttr>() || 1521651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FuncDecl->hasAttr<CFReturnsNotRetainedAttr>() || 1522651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FuncDecl->hasAttr<NSReturnsRetainedAttr>() || 1523651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FuncDecl->hasAttr<NSReturnsNotRetainedAttr>() || 1524651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FuncDecl->hasAttr<NSReturnsAutoreleasedAttr>()); 1525a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian 152687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar // Trivial case of when function is annotated and has no argument. 1527a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian if (FuncIsReturnAnnotated && FuncDecl->getNumParams() == 0) 1528a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian return CF_BRIDGING_NONE; 1529a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian 1530a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian bool ReturnCFAudited = false; 1531a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian if (!FuncIsReturnAnnotated) { 1532a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian RetEffect Ret = CE.getReturnValue(); 1533a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian if (Ret.getObjKind() == RetEffect::CF && 15345f7ac67c84e7b9a04fa4c5065e384f928c8f812fFariborz Jahanian (Ret.isOwned() || Ret.notOwned())) 1535a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian ReturnCFAudited = true; 1536651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines else if (!AuditedType(FuncDecl->getReturnType())) 1537a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian return CF_BRIDGING_NONE; 1538269cca13cdafab34073158476de0391d1839ecd3Fariborz Jahanian } 1539a46c6c3baa0bb24987b44ac7a5543fa60e8b639eFariborz Jahanian 1540a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian // At this point result type is audited for potential inclusion. 15416cb33a4e9e8298dfa4a8aa33ccc34ce68580f234Fariborz Jahanian // Now, how about argument types. 1542c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ArrayRef<ArgEffect> AEArgs = CE.getArgs(); 15436cb33a4e9e8298dfa4a8aa33ccc34ce68580f234Fariborz Jahanian unsigned i = 0; 1544a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian bool ArgCFAudited = false; 15456cb33a4e9e8298dfa4a8aa33ccc34ce68580f234Fariborz Jahanian for (FunctionDecl::param_const_iterator pi = FuncDecl->param_begin(), 15466cb33a4e9e8298dfa4a8aa33ccc34ce68580f234Fariborz Jahanian pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) { 1547a178593335e12761d4362eab0eff0c12ad081635Fariborz Jahanian const ParmVarDecl *pd = *pi; 15486cb33a4e9e8298dfa4a8aa33ccc34ce68580f234Fariborz Jahanian ArgEffect AE = AEArgs[i]; 1549a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian if (AE == DecRef /*CFConsumed annotated*/ || AE == IncRef) { 1550651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (AE == DecRef && !pd->hasAttr<CFConsumedAttr>()) 1551a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian ArgCFAudited = true; 1552a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian else if (AE == IncRef) 1553a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian ArgCFAudited = true; 1554a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian } 1555a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian else { 1556a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian QualType AT = pd->getType(); 1557a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian if (!AuditedType(AT)) { 1558c1cc488c3cf9ce7f7b7e211e891e2be7391e0e5aFariborz Jahanian AddCFAnnotations(Ctx, CE, FuncDecl, FuncIsReturnAnnotated); 1559a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian return CF_BRIDGING_NONE; 1560a178593335e12761d4362eab0eff0c12ad081635Fariborz Jahanian } 1561a46c6c3baa0bb24987b44ac7a5543fa60e8b639eFariborz Jahanian } 1562269cca13cdafab34073158476de0391d1839ecd3Fariborz Jahanian } 1563a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian if (ReturnCFAudited || ArgCFAudited) 1564a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian return CF_BRIDGING_ENABLE; 1565a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian 1566a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian return CF_BRIDGING_MAY_INCLUDE; 156746f4fd5938b0ff4ebbb83ba1df225f73d640613dFariborz Jahanian} 156846f4fd5938b0ff4ebbb83ba1df225f73d640613dFariborz Jahanian 1569d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanianvoid ObjCMigrateASTConsumer::migrateARCSafeAnnotation(ASTContext &Ctx, 1570d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian ObjCContainerDecl *CDecl) { 1571641645f00c22e1f55794537a43646214402e99a1Fariborz Jahanian if (!isa<ObjCInterfaceDecl>(CDecl) || CDecl->isDeprecated()) 1572d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian return; 1573d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian 1574d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian // migrate methods which can have instancetype as their result type. 1575651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto *Method : CDecl->methods()) 1576d76941102f17d5f4e88ef027151c20c95b745c8bFariborz Jahanian migrateCFAnnotation(Ctx, Method); 1577d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian} 1578d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian 1579a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanianvoid ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx, 1580a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian const CallEffects &CE, 1581c1cc488c3cf9ce7f7b7e211e891e2be7391e0e5aFariborz Jahanian const ObjCMethodDecl *MethodDecl, 1582c1cc488c3cf9ce7f7b7e211e891e2be7391e0e5aFariborz Jahanian bool ResultAnnotated) { 1583a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian // Annotate function. 1584c1cc488c3cf9ce7f7b7e211e891e2be7391e0e5aFariborz Jahanian if (!ResultAnnotated) { 1585d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian RetEffect Ret = CE.getReturnValue(); 15866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const char *AnnotationString = nullptr; 15874afe57965e19d9c9ba8070ac9901ed8a20e20fceFariborz Jahanian if (Ret.getObjKind() == RetEffect::CF) { 1588b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar if (Ret.isOwned() && NSAPIObj->isMacroDefined("CF_RETURNS_RETAINED")) 1589d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian AnnotationString = " CF_RETURNS_RETAINED"; 15904afe57965e19d9c9ba8070ac9901ed8a20e20fceFariborz Jahanian else if (Ret.notOwned() && 1591b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar NSAPIObj->isMacroDefined("CF_RETURNS_NOT_RETAINED")) 1592d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian AnnotationString = " CF_RETURNS_NOT_RETAINED"; 1593d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian } 15944afe57965e19d9c9ba8070ac9901ed8a20e20fceFariborz Jahanian else if (Ret.getObjKind() == RetEffect::ObjC) { 15957fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian ObjCMethodFamily OMF = MethodDecl->getMethodFamily(); 15967fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian switch (OMF) { 15977fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian case clang::OMF_alloc: 15987fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian case clang::OMF_new: 15997fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian case clang::OMF_copy: 16007fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian case clang::OMF_init: 16017fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian case clang::OMF_mutableCopy: 16027fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian break; 16037fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian 16047fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian default: 1605b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar if (Ret.isOwned() && NSAPIObj->isMacroDefined("NS_RETURNS_RETAINED")) 16067fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian AnnotationString = " NS_RETURNS_RETAINED"; 16077fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian break; 16087fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian } 16094afe57965e19d9c9ba8070ac9901ed8a20e20fceFariborz Jahanian } 16104afe57965e19d9c9ba8070ac9901ed8a20e20fceFariborz Jahanian 1611d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian if (AnnotationString) { 1612d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian edit::Commit commit(*Editor); 1613d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian commit.insertBefore(MethodDecl->getLocEnd(), AnnotationString); 1614d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian Editor->commit(commit); 1615d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian } 1616a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian } 1617c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ArrayRef<ArgEffect> AEArgs = CE.getArgs(); 1618a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian unsigned i = 0; 1619a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian for (ObjCMethodDecl::param_const_iterator pi = MethodDecl->param_begin(), 1620a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) { 1621a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian const ParmVarDecl *pd = *pi; 1622a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian ArgEffect AE = AEArgs[i]; 1623651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (AE == DecRef && !pd->hasAttr<CFConsumedAttr>() && 1624b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar NSAPIObj->isMacroDefined("CF_CONSUMED")) { 1625a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian edit::Commit commit(*Editor); 1626a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian commit.insertBefore(pd->getLocation(), "CF_CONSUMED "); 1627a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian Editor->commit(commit); 1628a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian } 1629a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian } 1630a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian} 1631a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian 16325f7ac67c84e7b9a04fa4c5065e384f928c8f812fFariborz Jahanianvoid ObjCMigrateASTConsumer::migrateAddMethodAnnotation( 1633a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian ASTContext &Ctx, 1634a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian const ObjCMethodDecl *MethodDecl) { 16354afe57965e19d9c9ba8070ac9901ed8a20e20fceFariborz Jahanian if (MethodDecl->hasBody() || MethodDecl->isImplicit()) 16365f7ac67c84e7b9a04fa4c5065e384f928c8f812fFariborz Jahanian return; 1637a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian 1638a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian CallEffects CE = CallEffects::getEffect(MethodDecl); 1639651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool MethodIsReturnAnnotated = (MethodDecl->hasAttr<CFReturnsRetainedAttr>() || 1640651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines MethodDecl->hasAttr<CFReturnsNotRetainedAttr>() || 1641651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines MethodDecl->hasAttr<NSReturnsRetainedAttr>() || 1642651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines MethodDecl->hasAttr<NSReturnsNotRetainedAttr>() || 1643651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines MethodDecl->hasAttr<NSReturnsAutoreleasedAttr>()); 1644b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar 1645b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar if (CE.getReceiver() == DecRefMsg && 1646651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines !MethodDecl->hasAttr<NSConsumesSelfAttr>() && 16477fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian MethodDecl->getMethodFamily() != OMF_init && 16487fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian MethodDecl->getMethodFamily() != OMF_release && 1649b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar NSAPIObj->isMacroDefined("NS_CONSUMES_SELF")) { 16507fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian edit::Commit commit(*Editor); 16517fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian commit.insertBefore(MethodDecl->getLocEnd(), " NS_CONSUMES_SELF"); 16527fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian Editor->commit(commit); 16537fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian } 1654a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian 165587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar // Trivial case of when function is annotated and has no argument. 1656a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian if (MethodIsReturnAnnotated && 1657a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian (MethodDecl->param_begin() == MethodDecl->param_end())) 16585f7ac67c84e7b9a04fa4c5065e384f928c8f812fFariborz Jahanian return; 1659a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian 1660a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian if (!MethodIsReturnAnnotated) { 1661a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian RetEffect Ret = CE.getReturnValue(); 16624afe57965e19d9c9ba8070ac9901ed8a20e20fceFariborz Jahanian if ((Ret.getObjKind() == RetEffect::CF || 16634afe57965e19d9c9ba8070ac9901ed8a20e20fceFariborz Jahanian Ret.getObjKind() == RetEffect::ObjC) && 16644afe57965e19d9c9ba8070ac9901ed8a20e20fceFariborz Jahanian (Ret.isOwned() || Ret.notOwned())) { 1665a7a2a24956a53541acad07583c92747044e5bb95Fariborz Jahanian AddCFAnnotations(Ctx, CE, MethodDecl, false); 1666a7a2a24956a53541acad07583c92747044e5bb95Fariborz Jahanian return; 1667651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } else if (!AuditedType(MethodDecl->getReturnType())) 16685f7ac67c84e7b9a04fa4c5065e384f928c8f812fFariborz Jahanian return; 1669d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian } 1670d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian 1671d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian // At this point result type is either annotated or audited. 1672d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian // Now, how about argument types. 1673c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ArrayRef<ArgEffect> AEArgs = CE.getArgs(); 1674d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian unsigned i = 0; 1675d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian for (ObjCMethodDecl::param_const_iterator pi = MethodDecl->param_begin(), 1676d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) { 1677d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian const ParmVarDecl *pd = *pi; 1678d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian ArgEffect AE = AEArgs[i]; 1679651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if ((AE == DecRef && !pd->hasAttr<CFConsumedAttr>()) || AE == IncRef || 1680a7a2a24956a53541acad07583c92747044e5bb95Fariborz Jahanian !AuditedType(pd->getType())) { 1681a7a2a24956a53541acad07583c92747044e5bb95Fariborz Jahanian AddCFAnnotations(Ctx, CE, MethodDecl, MethodIsReturnAnnotated); 1682a7a2a24956a53541acad07583c92747044e5bb95Fariborz Jahanian return; 1683d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian } 1684d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian } 168546f4fd5938b0ff4ebbb83ba1df225f73d640613dFariborz Jahanian} 168646f4fd5938b0ff4ebbb83ba1df225f73d640613dFariborz Jahanian 168730660a898545416f0fea2d717f16f75640001e38Ted Kremeneknamespace { 1688651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesclass SuperInitChecker : public RecursiveASTVisitor<SuperInitChecker> { 1689651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinespublic: 1690651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool shouldVisitTemplateInstantiations() const { return false; } 1691651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool shouldWalkTypesOfTypeLocs() const { return false; } 1692651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1693651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool VisitObjCMessageExpr(ObjCMessageExpr *E) { 1694651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (E->getReceiverKind() == ObjCMessageExpr::SuperInstance) { 1695651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (E->getMethodFamily() == OMF_init) 1696651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return false; 1697651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1698651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return true; 1699651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1700651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}; 17014967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar} // end anonymous namespace 1702651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1703651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic bool hasSuperInitCall(const ObjCMethodDecl *MD) { 1704651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return !SuperInitChecker().TraverseStmt(MD->getBody()); 1705651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 1706651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1707651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesvoid ObjCMigrateASTConsumer::inferDesignatedInitializers( 1708651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ASTContext &Ctx, 1709651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const ObjCImplementationDecl *ImplD) { 1710651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1711651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const ObjCInterfaceDecl *IFace = ImplD->getClassInterface(); 1712651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!IFace || IFace->hasDesignatedInitializers()) 1713651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return; 1714b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar if (!NSAPIObj->isMacroDefined("NS_DESIGNATED_INITIALIZER")) 1715651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return; 1716651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1717651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto *MD : ImplD->instance_methods()) { 1718651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (MD->isDeprecated() || 1719651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines MD->getMethodFamily() != OMF_init || 1720651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines MD->isDesignatedInitializerForTheInterface()) 1721651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 1722651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const ObjCMethodDecl *IFaceM = IFace->getMethod(MD->getSelector(), 1723651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines /*isInstance=*/true); 1724651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!IFaceM) 1725651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 1726651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (hasSuperInitCall(MD)) { 1727651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines edit::Commit commit(*Editor); 1728651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines commit.insert(IFaceM->getLocEnd(), " NS_DESIGNATED_INITIALIZER"); 1729651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Editor->commit(commit); 1730651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1731651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1732651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 1733651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1734176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesbool ObjCMigrateASTConsumer::InsertFoundation(ASTContext &Ctx, 1735176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines SourceLocation Loc) { 1736176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (FoundationIncluded) 1737176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return true; 1738176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (Loc.isInvalid()) 1739176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return false; 1740176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines edit::Commit commit(*Editor); 1741176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (Ctx.getLangOpts().Modules) 1742176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines commit.insert(Loc, "#ifndef NS_ENUM\n@import Foundation;\n#endif\n"); 1743176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines else 1744176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines commit.insert(Loc, "#ifndef NS_ENUM\n#import <Foundation/Foundation.h>\n#endif\n"); 1745176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Editor->commit(commit); 1746176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines FoundationIncluded = true; 1747176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return true; 1748176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines} 1749176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 1750651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesnamespace { 175130660a898545416f0fea2d717f16f75640001e38Ted Kremenek 175230660a898545416f0fea2d717f16f75640001e38Ted Kremenekclass RewritesReceiver : public edit::EditsReceiver { 175330660a898545416f0fea2d717f16f75640001e38Ted Kremenek Rewriter &Rewrite; 175430660a898545416f0fea2d717f16f75640001e38Ted Kremenek 175530660a898545416f0fea2d717f16f75640001e38Ted Kremenekpublic: 175630660a898545416f0fea2d717f16f75640001e38Ted Kremenek RewritesReceiver(Rewriter &Rewrite) : Rewrite(Rewrite) { } 175730660a898545416f0fea2d717f16f75640001e38Ted Kremenek 1758651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void insert(SourceLocation loc, StringRef text) override { 175930660a898545416f0fea2d717f16f75640001e38Ted Kremenek Rewrite.InsertText(loc, text); 176030660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 1761651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void replace(CharSourceRange range, StringRef text) override { 176230660a898545416f0fea2d717f16f75640001e38Ted Kremenek Rewrite.ReplaceText(range.getBegin(), Rewrite.getRangeSize(range), text); 176330660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 176430660a898545416f0fea2d717f16f75640001e38Ted Kremenek}; 176530660a898545416f0fea2d717f16f75640001e38Ted Kremenek 1766651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesclass JSONEditWriter : public edit::EditsReceiver { 1767651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SourceManager &SourceMgr; 1768651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines llvm::raw_ostream &OS; 1769651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1770651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinespublic: 1771651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines JSONEditWriter(SourceManager &SM, llvm::raw_ostream &OS) 1772651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines : SourceMgr(SM), OS(OS) { 1773651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "[\n"; 1774651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 177558878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar ~JSONEditWriter() override { OS << "]\n"; } 1776651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1777651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesprivate: 1778651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines struct EntryWriter { 1779651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SourceManager &SourceMgr; 1780651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines llvm::raw_ostream &OS; 1781651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1782651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines EntryWriter(SourceManager &SM, llvm::raw_ostream &OS) 1783651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines : SourceMgr(SM), OS(OS) { 1784651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " {\n"; 1785651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1786651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ~EntryWriter() { 1787651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " },\n"; 1788651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1789651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1790651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeLoc(SourceLocation Loc) { 1791651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FileID FID; 1792651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines unsigned Offset; 1793651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::tie(FID, Offset) = SourceMgr.getDecomposedLoc(Loc); 179487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar assert(FID.isValid()); 1795651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SmallString<200> Path = 1796651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines StringRef(SourceMgr.getFileEntryForID(FID)->getName()); 1797651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines llvm::sys::fs::make_absolute(Path); 1798651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " \"file\": \""; 1799651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS.write_escaped(Path.str()) << "\",\n"; 1800651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " \"offset\": " << Offset << ",\n"; 1801651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1802651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1803651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeRemove(CharSourceRange Range) { 1804651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines assert(Range.isCharRange()); 1805651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::pair<FileID, unsigned> Begin = 1806651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SourceMgr.getDecomposedLoc(Range.getBegin()); 1807651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::pair<FileID, unsigned> End = 1808651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SourceMgr.getDecomposedLoc(Range.getEnd()); 1809651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines assert(Begin.first == End.first); 1810651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines assert(Begin.second <= End.second); 1811651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines unsigned Length = End.second - Begin.second; 1812651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1813651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " \"remove\": " << Length << ",\n"; 1814651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1815651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1816651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeText(StringRef Text) { 1817651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " \"text\": \""; 1818651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS.write_escaped(Text) << "\",\n"; 1819651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1820651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines }; 1821651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1822651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void insert(SourceLocation Loc, StringRef Text) override { 1823651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines EntryWriter Writer(SourceMgr, OS); 1824651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Writer.writeLoc(Loc); 1825651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Writer.writeText(Text); 1826651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1827651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1828651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void replace(CharSourceRange Range, StringRef Text) override { 1829651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines EntryWriter Writer(SourceMgr, OS); 1830651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Writer.writeLoc(Range.getBegin()); 1831651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Writer.writeRemove(Range); 1832651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Writer.writeText(Text); 1833651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1834651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1835651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void remove(CharSourceRange Range) override { 1836651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines EntryWriter Writer(SourceMgr, OS); 1837651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Writer.writeLoc(Range.getBegin()); 1838651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Writer.writeRemove(Range); 1839651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1840651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}; 1841651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 18424967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar} // end anonymous namespace 184330660a898545416f0fea2d717f16f75640001e38Ted Kremenek 184430660a898545416f0fea2d717f16f75640001e38Ted Kremenekvoid ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) { 1845baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian 1846baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian TranslationUnitDecl *TU = Ctx.getTranslationUnitDecl(); 1847081099d302b79d1746c7a39da14e3265971eb718Fariborz Jahanian if (ASTMigrateActions & FrontendOptions::ObjCMT_MigrateDecls) { 1848d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian for (DeclContext::decl_iterator D = TU->decls_begin(), DEnd = TU->decls_end(); 1849d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian D != DEnd; ++D) { 1850e909a720149ba5025209096fb9ed17e0162c8873Argyrios Kyrtzidis FileID FID = PP.getSourceManager().getFileID((*D)->getLocation()); 185187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if (FID.isValid()) 185287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if (FileId.isValid() && FileId != FID) { 1853b8941a15b6b5477a81c189614d0129070ac099f1Fariborz Jahanian if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) 1854b8941a15b6b5477a81c189614d0129070ac099f1Fariborz Jahanian AnnotateImplicitBridging(Ctx); 1855b8941a15b6b5477a81c189614d0129070ac099f1Fariborz Jahanian } 1856b8941a15b6b5477a81c189614d0129070ac099f1Fariborz Jahanian 1857d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian if (ObjCInterfaceDecl *CDecl = dyn_cast<ObjCInterfaceDecl>(*D)) 1858651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (canModify(CDecl)) 185958878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar migrateObjCContainerDecl(Ctx, CDecl); 18606d754e9a9d6591e8fc5eedc144cc70a7e539ba6fFariborz Jahanian if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(*D)) { 1861651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (canModify(CatDecl)) 186258878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar migrateObjCContainerDecl(Ctx, CatDecl); 18636d754e9a9d6591e8fc5eedc144cc70a7e539ba6fFariborz Jahanian } 186458878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(*D)) { 1865651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ObjCProtocolDecls.insert(PDecl->getCanonicalDecl()); 186658878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar if (canModify(PDecl)) 186758878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar migrateObjCContainerDecl(Ctx, PDecl); 186858878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar } 18697556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian else if (const ObjCImplementationDecl *ImpDecl = 1870b8941a15b6b5477a81c189614d0129070ac099f1Fariborz Jahanian dyn_cast<ObjCImplementationDecl>(*D)) { 1871651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if ((ASTMigrateActions & FrontendOptions::ObjCMT_ProtocolConformance) && 1872651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines canModify(ImpDecl)) 1873b8941a15b6b5477a81c189614d0129070ac099f1Fariborz Jahanian migrateProtocolConformance(Ctx, ImpDecl); 1874b8941a15b6b5477a81c189614d0129070ac099f1Fariborz Jahanian } 1875bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian else if (const EnumDecl *ED = dyn_cast<EnumDecl>(*D)) { 1876b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian if (!(ASTMigrateActions & FrontendOptions::ObjCMT_NsMacros)) 1877b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian continue; 1878651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!canModify(ED)) 1879651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 1880bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian DeclContext::decl_iterator N = D; 1881b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian if (++N != DEnd) { 1882b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian const TypedefDecl *TD = dyn_cast<TypedefDecl>(*N); 1883b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian if (migrateNSEnumDecl(Ctx, ED, TD) && TD) 1884b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian D++; 1885b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian } 1886b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian else 18876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines migrateNSEnumDecl(Ctx, ED, /*TypedefDecl */nullptr); 1888d2dab64a438b7b8d57f8a10883e107d2bc0988edFariborz Jahanian } 1889d2dab64a438b7b8d57f8a10883e107d2bc0988edFariborz Jahanian else if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(*D)) { 1890d33884f1e2e3189ee2db75cc72d90ea854f6bc68Fariborz Jahanian if (!(ASTMigrateActions & FrontendOptions::ObjCMT_NsMacros)) 1891d33884f1e2e3189ee2db75cc72d90ea854f6bc68Fariborz Jahanian continue; 1892651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!canModify(TD)) 1893651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 1894d33884f1e2e3189ee2db75cc72d90ea854f6bc68Fariborz Jahanian DeclContext::decl_iterator N = D; 1895d33884f1e2e3189ee2db75cc72d90ea854f6bc68Fariborz Jahanian if (++N == DEnd) 1896d33884f1e2e3189ee2db75cc72d90ea854f6bc68Fariborz Jahanian continue; 1897d33884f1e2e3189ee2db75cc72d90ea854f6bc68Fariborz Jahanian if (const EnumDecl *ED = dyn_cast<EnumDecl>(*N)) { 1898b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian if (++N != DEnd) 1899d33884f1e2e3189ee2db75cc72d90ea854f6bc68Fariborz Jahanian if (const TypedefDecl *TDF = dyn_cast<TypedefDecl>(*N)) { 1900d33884f1e2e3189ee2db75cc72d90ea854f6bc68Fariborz Jahanian // prefer typedef-follows-enum to enum-follows-typedef pattern. 1901d33884f1e2e3189ee2db75cc72d90ea854f6bc68Fariborz Jahanian if (migrateNSEnumDecl(Ctx, ED, TDF)) { 1902d33884f1e2e3189ee2db75cc72d90ea854f6bc68Fariborz Jahanian ++D; ++D; 1903d33884f1e2e3189ee2db75cc72d90ea854f6bc68Fariborz Jahanian CacheObjCNSIntegerTypedefed(TD); 1904b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian continue; 1905b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian } 1906d2dab64a438b7b8d57f8a10883e107d2bc0988edFariborz Jahanian } 1907d33884f1e2e3189ee2db75cc72d90ea854f6bc68Fariborz Jahanian if (migrateNSEnumDecl(Ctx, ED, TD)) { 1908d33884f1e2e3189ee2db75cc72d90ea854f6bc68Fariborz Jahanian ++D; 1909d33884f1e2e3189ee2db75cc72d90ea854f6bc68Fariborz Jahanian continue; 1910d33884f1e2e3189ee2db75cc72d90ea854f6bc68Fariborz Jahanian } 1911b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian } 1912d33884f1e2e3189ee2db75cc72d90ea854f6bc68Fariborz Jahanian CacheObjCNSIntegerTypedefed(TD); 1913b8941a15b6b5477a81c189614d0129070ac099f1Fariborz Jahanian } 1914b8941a15b6b5477a81c189614d0129070ac099f1Fariborz Jahanian else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*D)) { 1915651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if ((ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) && 1916651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines canModify(FD)) 1917b8941a15b6b5477a81c189614d0129070ac099f1Fariborz Jahanian migrateCFAnnotation(Ctx, FD); 1918bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian } 1919086d565d2d3b8e72f95492d3a2cefd09e1718f2aFariborz Jahanian 1920d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian if (ObjCContainerDecl *CDecl = dyn_cast<ObjCContainerDecl>(*D)) { 1921651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool CanModify = canModify(CDecl); 1922d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian // migrate methods which can have instancetype as their result type. 1923651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if ((ASTMigrateActions & FrontendOptions::ObjCMT_Instancetype) && 1924651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CanModify) 1925b8941a15b6b5477a81c189614d0129070ac099f1Fariborz Jahanian migrateAllMethodInstaceType(Ctx, CDecl); 1926d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian // annotate methods with CF annotations. 1927651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if ((ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) && 1928651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CanModify) 1929b8941a15b6b5477a81c189614d0129070ac099f1Fariborz Jahanian migrateARCSafeAnnotation(Ctx, CDecl); 1930d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian } 1931651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1932651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (const ObjCImplementationDecl * 1933651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ImplD = dyn_cast<ObjCImplementationDecl>(*D)) { 1934651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if ((ASTMigrateActions & FrontendOptions::ObjCMT_DesignatedInitializer) && 1935651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines canModify(ImplD)) 1936651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines inferDesignatedInitializers(Ctx, ImplD); 1937651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1938d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian } 1939b8941a15b6b5477a81c189614d0129070ac099f1Fariborz Jahanian if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) 1940b8941a15b6b5477a81c189614d0129070ac099f1Fariborz Jahanian AnnotateImplicitBridging(Ctx); 1941dead50d347e9517d80f007a93df6295f66aa0f00Fariborz Jahanian } 1942baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian 1943651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (IsOutputFile) { 1944176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines std::error_code EC; 1945176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines llvm::raw_fd_ostream OS(MigrateDir, EC, llvm::sys::fs::F_None); 1946176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (EC) { 1947651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines DiagnosticsEngine &Diags = Ctx.getDiagnostics(); 1948651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Diags.Report(Diags.getCustomDiagID(DiagnosticsEngine::Error, "%0")) 1949176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines << EC.message(); 1950651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return; 1951651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1952651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1953651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines JSONEditWriter Writer(Ctx.getSourceManager(), OS); 1954651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Editor->applyRewrites(Writer); 1955651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return; 1956651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1957651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 19584e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie Rewriter rewriter(Ctx.getSourceManager(), Ctx.getLangOpts()); 195930660a898545416f0fea2d717f16f75640001e38Ted Kremenek RewritesReceiver Rec(rewriter); 196030660a898545416f0fea2d717f16f75640001e38Ted Kremenek Editor->applyRewrites(Rec); 196130660a898545416f0fea2d717f16f75640001e38Ted Kremenek 196230660a898545416f0fea2d717f16f75640001e38Ted Kremenek for (Rewriter::buffer_iterator 196330660a898545416f0fea2d717f16f75640001e38Ted Kremenek I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) { 196430660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileID FID = I->first; 196530660a898545416f0fea2d717f16f75640001e38Ted Kremenek RewriteBuffer &buf = I->second; 196630660a898545416f0fea2d717f16f75640001e38Ted Kremenek const FileEntry *file = Ctx.getSourceManager().getFileEntryForID(FID); 196730660a898545416f0fea2d717f16f75640001e38Ted Kremenek assert(file); 1968cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko SmallString<512> newText; 196930660a898545416f0fea2d717f16f75640001e38Ted Kremenek llvm::raw_svector_ostream vecOS(newText); 197030660a898545416f0fea2d717f16f75640001e38Ted Kremenek buf.write(vecOS); 1971176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines std::unique_ptr<llvm::MemoryBuffer> memBuf( 1972176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines llvm::MemoryBuffer::getMemBufferCopy( 1973176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines StringRef(newText.data(), newText.size()), file->getName())); 1974cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko SmallString<64> filePath(file->getName()); 197530660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileMgr.FixupRelativePath(filePath); 1976176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Remapper.remap(filePath.str(), std::move(memBuf)); 197730660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 197830660a898545416f0fea2d717f16f75640001e38Ted Kremenek 197930660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (IsOutputFile) { 198030660a898545416f0fea2d717f16f75640001e38Ted Kremenek Remapper.flushToFile(MigrateDir, Ctx.getDiagnostics()); 198130660a898545416f0fea2d717f16f75640001e38Ted Kremenek } else { 198230660a898545416f0fea2d717f16f75640001e38Ted Kremenek Remapper.flushToDisk(MigrateDir, Ctx.getDiagnostics()); 198330660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 198430660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 198530660a898545416f0fea2d717f16f75640001e38Ted Kremenek 198630660a898545416f0fea2d717f16f75640001e38Ted Kremenekbool MigrateSourceAction::BeginInvocation(CompilerInstance &CI) { 1987013a254a5b85cfb54066e4022649368689c9ab06Argyrios Kyrtzidis CI.getDiagnostics().setIgnoreAllWarnings(true); 198830660a898545416f0fea2d717f16f75640001e38Ted Kremenek return true; 198930660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 199030660a898545416f0fea2d717f16f75640001e38Ted Kremenek 19912c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidisstatic std::vector<std::string> getWhiteListFilenames(StringRef DirPath) { 19922c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis using namespace llvm::sys::fs; 19932c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis using namespace llvm::sys::path; 19942c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis 19952c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis std::vector<std::string> Filenames; 19962c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis if (DirPath.empty() || !is_directory(DirPath)) 19972c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis return Filenames; 1998c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 1999c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::error_code EC; 20002c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis directory_iterator DI = directory_iterator(DirPath, EC); 20012c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis directory_iterator DE; 20022c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis for (; !EC && DI != DE; DI = DI.increment(EC)) { 20032c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis if (is_regular_file(DI->path())) 20042c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis Filenames.push_back(filename(DI->path())); 20052c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis } 20062c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis 20072c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis return Filenames; 20082c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis} 20092c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis 2010176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesstd::unique_ptr<ASTConsumer> 2011176edba5311f6eff0cad2631449885ddf4fbc9eaStephen HinesMigrateSourceAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { 201237ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis PPConditionalDirectiveRecord * 201337ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis PPRec = new PPConditionalDirectiveRecord(CI.getSourceManager()); 201402593f5c9769851b8fcf6f78736e8b63ce9692e3Argyrios Kyrtzidis unsigned ObjCMTAction = CI.getFrontendOpts().ObjCMTAction; 20159887f260a8d59d47ed31b5fc689909b464ffc18fArgyrios Kyrtzidis unsigned ObjCMTOpts = ObjCMTAction; 20169887f260a8d59d47ed31b5fc689909b464ffc18fArgyrios Kyrtzidis // These are companion flags, they do not enable transformations. 20179887f260a8d59d47ed31b5fc689909b464ffc18fArgyrios Kyrtzidis ObjCMTOpts &= ~(FrontendOptions::ObjCMT_AtomicProperty | 20189887f260a8d59d47ed31b5fc689909b464ffc18fArgyrios Kyrtzidis FrontendOptions::ObjCMT_NsAtomicIOSOnlyProperty); 20199887f260a8d59d47ed31b5fc689909b464ffc18fArgyrios Kyrtzidis if (ObjCMTOpts == FrontendOptions::ObjCMT_None) { 202002593f5c9769851b8fcf6f78736e8b63ce9692e3Argyrios Kyrtzidis // If no specific option was given, enable literals+subscripting transforms 202102593f5c9769851b8fcf6f78736e8b63ce9692e3Argyrios Kyrtzidis // by default. 20229887f260a8d59d47ed31b5fc689909b464ffc18fArgyrios Kyrtzidis ObjCMTAction |= FrontendOptions::ObjCMT_Literals | 20239887f260a8d59d47ed31b5fc689909b464ffc18fArgyrios Kyrtzidis FrontendOptions::ObjCMT_Subscripting; 202402593f5c9769851b8fcf6f78736e8b63ce9692e3Argyrios Kyrtzidis } 2025176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines CI.getPreprocessor().addPPCallbacks(std::unique_ptr<PPCallbacks>(PPRec)); 20262c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis std::vector<std::string> WhiteList = 20272c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis getWhiteListFilenames(CI.getFrontendOpts().ObjCMTWhiteListPath); 2028176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return llvm::make_unique<ObjCMigrateASTConsumer>( 2029176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines CI.getFrontendOpts().OutputFile, ObjCMTAction, Remapper, 2030176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines CI.getFileManager(), PPRec, CI.getPreprocessor(), 2031176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines /*isOutputFile=*/true, WhiteList); 203230660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 2033651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2034651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesnamespace { 2035651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstruct EditEntry { 2036651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const FileEntry *File; 2037651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines unsigned Offset; 2038651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines unsigned RemoveLen; 2039651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string Text; 2040651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2041651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines EditEntry() : File(), Offset(), RemoveLen() {} 2042651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}; 20434967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar} // end anonymous namespace 2044651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2045651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesnamespace llvm { 2046651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinestemplate<> struct DenseMapInfo<EditEntry> { 2047651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines static inline EditEntry getEmptyKey() { 2048651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines EditEntry Entry; 2049651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Entry.Offset = unsigned(-1); 2050651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return Entry; 2051651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2052651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines static inline EditEntry getTombstoneKey() { 2053651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines EditEntry Entry; 2054651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Entry.Offset = unsigned(-2); 2055651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return Entry; 2056651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2057651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines static unsigned getHashValue(const EditEntry& Val) { 2058651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines llvm::FoldingSetNodeID ID; 2059651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ID.AddPointer(Val.File); 2060651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ID.AddInteger(Val.Offset); 2061651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ID.AddInteger(Val.RemoveLen); 2062651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ID.AddString(Val.Text); 2063651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return ID.ComputeHash(); 2064651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2065651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines static bool isEqual(const EditEntry &LHS, const EditEntry &RHS) { 2066651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return LHS.File == RHS.File && 2067651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines LHS.Offset == RHS.Offset && 2068651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines LHS.RemoveLen == RHS.RemoveLen && 2069651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines LHS.Text == RHS.Text; 2070651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2071651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}; 20724967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar} // end namespace llvm 2073651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2074651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesnamespace { 2075651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesclass RemapFileParser { 2076651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FileManager &FileMgr; 2077651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2078651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinespublic: 2079651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines RemapFileParser(FileManager &FileMgr) : FileMgr(FileMgr) { } 2080651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2081651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool parse(StringRef File, SmallVectorImpl<EditEntry> &Entries) { 2082651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines using namespace llvm::yaml; 2083651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2084c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr = 2085c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines llvm::MemoryBuffer::getFile(File); 2086c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (!FileBufOrErr) 2087651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return true; 2088651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2089651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines llvm::SourceMgr SM; 2090176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Stream YAMLStream(FileBufOrErr.get()->getMemBufferRef(), SM); 2091651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines document_iterator I = YAMLStream.begin(); 2092651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (I == YAMLStream.end()) 2093651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return true; 2094651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Node *Root = I->getRoot(); 2095651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!Root) 2096651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return true; 2097651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2098651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SequenceNode *SeqNode = dyn_cast<SequenceNode>(Root); 2099651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!SeqNode) 2100651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return true; 2101651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2102651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (SequenceNode::iterator 2103651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines AI = SeqNode->begin(), AE = SeqNode->end(); AI != AE; ++AI) { 2104651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines MappingNode *MapNode = dyn_cast<MappingNode>(&*AI); 2105651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!MapNode) 2106651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 2107651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines parseEdit(MapNode, Entries); 2108651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2109651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2110651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return false; 2111651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2112651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2113651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesprivate: 2114651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void parseEdit(llvm::yaml::MappingNode *Node, 2115651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SmallVectorImpl<EditEntry> &Entries) { 2116651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines using namespace llvm::yaml; 2117651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines EditEntry Entry; 2118651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool Ignore = false; 2119651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2120651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (MappingNode::iterator 2121651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines KVI = Node->begin(), KVE = Node->end(); KVI != KVE; ++KVI) { 2122651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ScalarNode *KeyString = dyn_cast<ScalarNode>((*KVI).getKey()); 2123651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!KeyString) 2124651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 2125651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SmallString<10> KeyStorage; 2126651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines StringRef Key = KeyString->getValue(KeyStorage); 2127651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2128651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ScalarNode *ValueString = dyn_cast<ScalarNode>((*KVI).getValue()); 2129651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!ValueString) 2130651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 2131651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SmallString<64> ValueStorage; 2132651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines StringRef Val = ValueString->getValue(ValueStorage); 2133651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2134651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Key == "file") { 2135651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const FileEntry *FE = FileMgr.getFile(Val); 2136651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!FE) 2137651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Ignore = true; 2138651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Entry.File = FE; 2139651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } else if (Key == "offset") { 2140651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Val.getAsInteger(10, Entry.Offset)) 2141651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Ignore = true; 2142651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } else if (Key == "remove") { 2143651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Val.getAsInteger(10, Entry.RemoveLen)) 2144651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Ignore = true; 2145651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } else if (Key == "text") { 2146651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Entry.Text = Val; 2147651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2148651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2149651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2150651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!Ignore) 2151651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Entries.push_back(Entry); 2152651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2153651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}; 21544967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar} // end anonymous namespace 2155651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2156651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic bool reportDiag(const Twine &Err, DiagnosticsEngine &Diag) { 2157651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Diag.Report(Diag.getCustomDiagID(DiagnosticsEngine::Error, "%0")) 2158651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << Err.str(); 2159651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return true; 2160651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 2161651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2162651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic std::string applyEditsToTemp(const FileEntry *FE, 2163651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ArrayRef<EditEntry> Edits, 2164651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FileManager &FileMgr, 2165651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines DiagnosticsEngine &Diag) { 2166651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines using namespace llvm::sys; 2167651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2168651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SourceManager SM(Diag, FileMgr); 2169651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FileID FID = SM.createFileID(FE, SourceLocation(), SrcMgr::C_User); 2170651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines LangOptions LangOpts; 2171651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines edit::EditedSource Editor(SM, LangOpts); 2172651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (ArrayRef<EditEntry>::iterator 2173651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines I = Edits.begin(), E = Edits.end(); I != E; ++I) { 2174651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const EditEntry &Entry = *I; 2175651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines assert(Entry.File == FE); 2176651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SourceLocation Loc = 2177651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SM.getLocForStartOfFile(FID).getLocWithOffset(Entry.Offset); 2178651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CharSourceRange Range; 2179651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Entry.RemoveLen != 0) { 2180651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Range = CharSourceRange::getCharRange(Loc, 2181651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Loc.getLocWithOffset(Entry.RemoveLen)); 2182651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2183651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2184651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines edit::Commit commit(Editor); 2185651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Range.isInvalid()) { 2186651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines commit.insert(Loc, Entry.Text); 2187651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } else if (Entry.Text.empty()) { 2188651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines commit.remove(Range); 2189651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } else { 2190651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines commit.replace(Range, Entry.Text); 2191651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2192651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Editor.commit(commit); 2193651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2194651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2195651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Rewriter rewriter(SM, LangOpts); 2196651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines RewritesReceiver Rec(rewriter); 2197651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Editor.applyRewrites(Rec); 2198651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2199651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const RewriteBuffer *Buf = rewriter.getRewriteBufferFor(FID); 2200651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SmallString<512> NewText; 2201651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines llvm::raw_svector_ostream OS(NewText); 2202651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Buf->write(OS); 2203651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2204651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SmallString<64> TempPath; 2205651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines int FD; 2206651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (fs::createTemporaryFile(path::filename(FE->getName()), 220787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar path::extension(FE->getName()).drop_front(), FD, 2208651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines TempPath)) { 2209651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines reportDiag("Could not create file: " + TempPath.str(), Diag); 2210651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return std::string(); 2211651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2212651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2213651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines llvm::raw_fd_ostream TmpOut(FD, /*shouldClose=*/true); 2214651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines TmpOut.write(NewText.data(), NewText.size()); 2215651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines TmpOut.close(); 2216651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2217651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return TempPath.str(); 2218651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 2219651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2220651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesbool arcmt::getFileRemappingsFromFileList( 2221651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<std::pair<std::string,std::string> > &remap, 2222651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ArrayRef<StringRef> remapFiles, 2223651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines DiagnosticConsumer *DiagClient) { 2224651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool hasErrorOccurred = false; 2225651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2226651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FileSystemOptions FSOpts; 2227651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FileManager FileMgr(FSOpts); 2228651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines RemapFileParser Parser(FileMgr); 2229651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2230651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 2231651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines IntrusiveRefCntPtr<DiagnosticsEngine> Diags( 2232651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines new DiagnosticsEngine(DiagID, new DiagnosticOptions, 2233651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines DiagClient, /*ShouldOwnClient=*/false)); 2234651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2235651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines typedef llvm::DenseMap<const FileEntry *, std::vector<EditEntry> > 2236651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FileEditEntriesTy; 2237651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FileEditEntriesTy FileEditEntries; 2238651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2239651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines llvm::DenseSet<EditEntry> EntriesSet; 2240651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2241651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (ArrayRef<StringRef>::iterator 2242651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines I = remapFiles.begin(), E = remapFiles.end(); I != E; ++I) { 2243651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SmallVector<EditEntry, 16> Entries; 2244651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Parser.parse(*I, Entries)) 2245651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 2246651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2247651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (SmallVectorImpl<EditEntry>::iterator 2248651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines EI = Entries.begin(), EE = Entries.end(); EI != EE; ++EI) { 2249651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines EditEntry &Entry = *EI; 2250651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!Entry.File) 2251651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 2252651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::pair<llvm::DenseSet<EditEntry>::iterator, bool> 2253651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Insert = EntriesSet.insert(Entry); 2254651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!Insert.second) 2255651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 2256651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2257651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FileEditEntries[Entry.File].push_back(Entry); 2258651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2259651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2260651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2261651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (FileEditEntriesTy::iterator 2262651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines I = FileEditEntries.begin(), E = FileEditEntries.end(); I != E; ++I) { 2263651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string TempFile = applyEditsToTemp(I->first, I->second, 2264651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FileMgr, *Diags); 2265651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (TempFile.empty()) { 2266651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines hasErrorOccurred = true; 2267651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 2268651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2269651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2270b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar remap.emplace_back(I->first->getName(), TempFile); 2271651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2272651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2273651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return hasErrorOccurred; 2274651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 2275