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 18030660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 18130660a898545416f0fea2d717f16f75640001e38Ted Kremenek 18230660a898545416f0fea2d717f16f75640001e38Ted KremenekObjCMigrateAction::ObjCMigrateAction(FrontendAction *WrappedAction, 18374fd551c0ba344d62aedc8636ed81b45652f04d8Fariborz Jahanian StringRef migrateDir, 18474fd551c0ba344d62aedc8636ed81b45652f04d8Fariborz Jahanian unsigned migrateAction) 18530660a898545416f0fea2d717f16f75640001e38Ted Kremenek : WrapperFrontendAction(WrappedAction), MigrateDir(migrateDir), 18674fd551c0ba344d62aedc8636ed81b45652f04d8Fariborz Jahanian ObjCMigAction(migrateAction), 1876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines CompInst(nullptr) { 18830660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (MigrateDir.empty()) 18930660a898545416f0fea2d717f16f75640001e38Ted Kremenek MigrateDir = "."; // user current directory if none is given. 19030660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 19130660a898545416f0fea2d717f16f75640001e38Ted Kremenek 192176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesstd::unique_ptr<ASTConsumer> 193176edba5311f6eff0cad2631449885ddf4fbc9eaStephen HinesObjCMigrateAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { 19437ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis PPConditionalDirectiveRecord * 19537ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis PPRec = new PPConditionalDirectiveRecord(CompInst->getSourceManager()); 196176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines CI.getPreprocessor().addPPCallbacks(std::unique_ptr<PPCallbacks>(PPRec)); 197176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines std::vector<std::unique_ptr<ASTConsumer>> Consumers; 198176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Consumers.push_back(WrapperFrontendAction::CreateASTConsumer(CI, InFile)); 199176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Consumers.push_back(llvm::make_unique<ObjCMigrateASTConsumer>( 200176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines MigrateDir, ObjCMigAction, Remapper, CompInst->getFileManager(), PPRec, 201176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines CompInst->getPreprocessor(), false, None)); 202176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return llvm::make_unique<MultiplexConsumer>(std::move(Consumers)); 20330660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 20430660a898545416f0fea2d717f16f75640001e38Ted Kremenek 20530660a898545416f0fea2d717f16f75640001e38Ted Kremenekbool ObjCMigrateAction::BeginInvocation(CompilerInstance &CI) { 20630660a898545416f0fea2d717f16f75640001e38Ted Kremenek Remapper.initFromDisk(MigrateDir, CI.getDiagnostics(), 20730660a898545416f0fea2d717f16f75640001e38Ted Kremenek /*ignoreIfFilesChanges=*/true); 20830660a898545416f0fea2d717f16f75640001e38Ted Kremenek CompInst = &CI; 20930660a898545416f0fea2d717f16f75640001e38Ted Kremenek CI.getDiagnostics().setIgnoreAllWarnings(true); 21030660a898545416f0fea2d717f16f75640001e38Ted Kremenek return true; 21130660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 21230660a898545416f0fea2d717f16f75640001e38Ted Kremenek 21330660a898545416f0fea2d717f16f75640001e38Ted Kremeneknamespace { 214176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines // FIXME. This duplicates one in RewriteObjCFoundationAPI.cpp 215176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines bool subscriptOperatorNeedsParens(const Expr *FullExpr) { 216176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines const Expr* Expr = FullExpr->IgnoreImpCasts(); 217a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar return !(isa<ArraySubscriptExpr>(Expr) || isa<CallExpr>(Expr) || 218a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar isa<DeclRefExpr>(Expr) || isa<CXXNamedCastExpr>(Expr) || 219a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar isa<CXXConstructExpr>(Expr) || isa<CXXThisExpr>(Expr) || 220a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar isa<CXXTypeidExpr>(Expr) || 221a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar isa<CXXUnresolvedConstructExpr>(Expr) || 222a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar isa<ObjCMessageExpr>(Expr) || isa<ObjCPropertyRefExpr>(Expr) || 223a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar isa<ObjCProtocolExpr>(Expr) || isa<MemberExpr>(Expr) || 224a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar isa<ObjCIvarRefExpr>(Expr) || isa<ParenExpr>(FullExpr) || 225a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar isa<ParenListExpr>(Expr) || isa<SizeOfPackExpr>(Expr)); 226176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 227176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 228176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines /// \brief - Rewrite message expression for Objective-C setter and getters into 229176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines /// property-dot syntax. 230176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines bool rewriteToPropertyDotSyntax(const ObjCMessageExpr *Msg, 231176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Preprocessor &PP, 232176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines const NSAPI &NS, edit::Commit &commit, 233176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines const ParentMap *PMap) { 234176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (!Msg || Msg->isImplicit() || 2350e2c34f92f00628d48968dfea096d36381f494cbStephen Hines (Msg->getReceiverKind() != ObjCMessageExpr::Instance && 2360e2c34f92f00628d48968dfea096d36381f494cbStephen Hines Msg->getReceiverKind() != ObjCMessageExpr::SuperInstance)) 237176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return false; 2380e2c34f92f00628d48968dfea096d36381f494cbStephen Hines if (const Expr *Receiver = Msg->getInstanceReceiver()) 2390e2c34f92f00628d48968dfea096d36381f494cbStephen Hines if (Receiver->getType()->isObjCBuiltinType()) 2400e2c34f92f00628d48968dfea096d36381f494cbStephen Hines return false; 2410e2c34f92f00628d48968dfea096d36381f494cbStephen Hines 242176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines const ObjCMethodDecl *Method = Msg->getMethodDecl(); 243176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (!Method) 244176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return false; 245176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (!Method->isPropertyAccessor()) 246176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return false; 247176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 248176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines const ObjCPropertyDecl *Prop = Method->findPropertyDecl(); 249176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (!Prop) 250176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return false; 251176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 252176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines SourceRange MsgRange = Msg->getSourceRange(); 2530e2c34f92f00628d48968dfea096d36381f494cbStephen Hines bool ReceiverIsSuper = 2540e2c34f92f00628d48968dfea096d36381f494cbStephen Hines (Msg->getReceiverKind() == ObjCMessageExpr::SuperInstance); 2550e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // for 'super' receiver is nullptr. 256176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines const Expr *receiver = Msg->getInstanceReceiver(); 2570e2c34f92f00628d48968dfea096d36381f494cbStephen Hines bool NeedsParen = 2580e2c34f92f00628d48968dfea096d36381f494cbStephen Hines ReceiverIsSuper ? false : subscriptOperatorNeedsParens(receiver); 259176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines bool IsGetter = (Msg->getNumArgs() == 0); 260176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (IsGetter) { 261176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines // Find space location range between receiver expression and getter method. 2620e2c34f92f00628d48968dfea096d36381f494cbStephen Hines SourceLocation BegLoc = 2630e2c34f92f00628d48968dfea096d36381f494cbStephen Hines ReceiverIsSuper ? Msg->getSuperLoc() : receiver->getLocEnd(); 264176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines BegLoc = PP.getLocForEndOfToken(BegLoc); 265176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines SourceLocation EndLoc = Msg->getSelectorLoc(0); 266176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines SourceRange SpaceRange(BegLoc, EndLoc); 267176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines std::string PropertyDotString; 268176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines // rewrite getter method expression into: receiver.property or 269176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines // (receiver).property 270176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (NeedsParen) { 271176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines commit.insertBefore(receiver->getLocStart(), "("); 272176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines PropertyDotString = ")."; 273176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 274176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines else 275176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines PropertyDotString = "."; 276176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines PropertyDotString += Prop->getName(); 277176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines commit.replace(SpaceRange, PropertyDotString); 278176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 279176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines // remove '[' ']' 280176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines commit.replace(SourceRange(MsgRange.getBegin(), MsgRange.getBegin()), ""); 281176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines commit.replace(SourceRange(MsgRange.getEnd(), MsgRange.getEnd()), ""); 282176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } else { 283176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (NeedsParen) 2840e2c34f92f00628d48968dfea096d36381f494cbStephen Hines commit.insertWrap("(", receiver->getSourceRange(), ")"); 285176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines std::string PropertyDotString = "."; 286176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines PropertyDotString += Prop->getName(); 287176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines PropertyDotString += " ="; 288176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines const Expr*const* Args = Msg->getArgs(); 289176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines const Expr *RHS = Args[0]; 290176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (!RHS) 291176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return false; 2920e2c34f92f00628d48968dfea096d36381f494cbStephen Hines SourceLocation BegLoc = 2930e2c34f92f00628d48968dfea096d36381f494cbStephen Hines ReceiverIsSuper ? Msg->getSuperLoc() : receiver->getLocEnd(); 294176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines BegLoc = PP.getLocForEndOfToken(BegLoc); 295176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines SourceLocation EndLoc = RHS->getLocStart(); 296176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines EndLoc = EndLoc.getLocWithOffset(-1); 2970e2c34f92f00628d48968dfea096d36381f494cbStephen Hines const char *colon = PP.getSourceManager().getCharacterData(EndLoc); 2980e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // Add a space after '=' if there is no space between RHS and '=' 2990e2c34f92f00628d48968dfea096d36381f494cbStephen Hines if (colon && colon[0] == ':') 3000e2c34f92f00628d48968dfea096d36381f494cbStephen Hines PropertyDotString += " "; 301176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines SourceRange Range(BegLoc, EndLoc); 302176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines commit.replace(Range, PropertyDotString); 303176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines // remove '[' ']' 304176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines commit.replace(SourceRange(MsgRange.getBegin(), MsgRange.getBegin()), ""); 305176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines commit.replace(SourceRange(MsgRange.getEnd(), MsgRange.getEnd()), ""); 306176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 307176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return true; 308176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 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. 348a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar for (Stmt *SubStmt : E->children()) 349a4de17562d13d7a8188108243c4cfbd52f33229aPirama 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}; 37230660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 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 591651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto *Prop : D->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()) 608651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto *Property : PDecl->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( 6188d8bfb3e52567b86add4bfa931023f2e2a291499Fariborz Jahanian Property->getDeclName().getAsIdentifierInfo())) 6198d8bfb3e52567b86add4bfa931023f2e2a291499Fariborz Jahanian return false; 6208d8bfb3e52567b86add4bfa931023f2e2a291499Fariborz Jahanian } 6218d8bfb3e52567b86add4bfa931023f2e2a291499Fariborz Jahanian else if (ObjCPropertyDecl *ClassProperty = dyn_cast<ObjCPropertyDecl>(R[0])) { 6228d8bfb3e52567b86add4bfa931023f2e2a291499Fariborz Jahanian if ((ClassProperty->getPropertyAttributes() 6238d8bfb3e52567b86add4bfa931023f2e2a291499Fariborz Jahanian != Property->getPropertyAttributes()) || 6248d8bfb3e52567b86add4bfa931023f2e2a291499Fariborz Jahanian !Ctx.hasSameType(ClassProperty->getType(), Property->getType())) 625ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian return false; 626ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian } 6278d8bfb3e52567b86add4bfa931023f2e2a291499Fariborz Jahanian else 6288d8bfb3e52567b86add4bfa931023f2e2a291499Fariborz Jahanian return false; 629ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian } 63034cb2a3ed535eebed87d1118e89d006eb324e156Fariborz Jahanian 631ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian // At this point, all required properties in this protocol conform to those 632ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian // declared in the class. 633ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian // Check that class implements the required methods of the protocol too. 63434cb2a3ed535eebed87d1118e89d006eb324e156Fariborz Jahanian bool HasAtleastOneRequiredMethod = false; 6358c355831ac3c9e8c12b23ca69b7587dcbd0439efFariborz Jahanian if (const ObjCProtocolDecl *PDecl = Protocol->getDefinition()) { 6368c355831ac3c9e8c12b23ca69b7587dcbd0439efFariborz Jahanian if (PDecl->meth_begin() == PDecl->meth_end()) 63734cb2a3ed535eebed87d1118e89d006eb324e156Fariborz Jahanian return HasAtleastOneRequiredProperty; 638651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto *MD : PDecl->methods()) { 6398c355831ac3c9e8c12b23ca69b7587dcbd0439efFariborz Jahanian if (MD->isImplicit()) 6408c355831ac3c9e8c12b23ca69b7587dcbd0439efFariborz Jahanian continue; 641ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian if (MD->getImplementationControl() == ObjCMethodDecl::Optional) 642ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian continue; 6430e2c34f92f00628d48968dfea096d36381f494cbStephen Hines DeclContext::lookup_result R = ImpDecl->lookup(MD->getDeclName()); 6448c355831ac3c9e8c12b23ca69b7587dcbd0439efFariborz Jahanian if (R.size() == 0) 6458c355831ac3c9e8c12b23ca69b7587dcbd0439efFariborz Jahanian return false; 64634cb2a3ed535eebed87d1118e89d006eb324e156Fariborz Jahanian bool match = false; 64734cb2a3ed535eebed87d1118e89d006eb324e156Fariborz Jahanian HasAtleastOneRequiredMethod = true; 648ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian for (unsigned I = 0, N = R.size(); I != N; ++I) 649ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian if (ObjCMethodDecl *ImpMD = dyn_cast<ObjCMethodDecl>(R[0])) 650ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian if (Ctx.ObjCMethodsAreEqual(MD, ImpMD)) { 651ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian match = true; 652ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian break; 653ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian } 654ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian if (!match) 655ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian return false; 656ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian } 6578c355831ac3c9e8c12b23ca69b7587dcbd0439efFariborz Jahanian } 658a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar return HasAtleastOneRequiredProperty || HasAtleastOneRequiredMethod; 659e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian} 660e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian 66144b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanianstatic bool rewriteToObjCInterfaceDecl(const ObjCInterfaceDecl *IDecl, 66244b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian llvm::SmallVectorImpl<ObjCProtocolDecl*> &ConformingProtocols, 66344b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian const NSAPI &NS, edit::Commit &commit) { 66444b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian const ObjCList<ObjCProtocolDecl> &Protocols = IDecl->getReferencedProtocols(); 66544b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian std::string ClassString; 66644b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian SourceLocation EndLoc = 66744b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian IDecl->getSuperClass() ? IDecl->getSuperClassLoc() : IDecl->getLocation(); 66844b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian 66944b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian if (Protocols.empty()) { 67044b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian ClassString = '<'; 67144b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) { 67244b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian ClassString += ConformingProtocols[i]->getNameAsString(); 67344b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian if (i != (e-1)) 67444b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian ClassString += ", "; 67544b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian } 67644b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian ClassString += "> "; 67744b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian } 67844b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian else { 67944b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian ClassString = ", "; 68044b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) { 68144b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian ClassString += ConformingProtocols[i]->getNameAsString(); 68244b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian if (i != (e-1)) 68344b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian ClassString += ", "; 68444b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian } 68544b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian ObjCInterfaceDecl::protocol_loc_iterator PL = IDecl->protocol_loc_end() - 1; 68644b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian EndLoc = *PL; 68744b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian } 68844b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian 68944b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian commit.insertAfterToken(EndLoc, ClassString); 69044b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian return true; 69144b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian} 69244b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian 693176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesstatic StringRef GetUnsignedName(StringRef NSIntegerName) { 694176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines StringRef UnsignedName = llvm::StringSwitch<StringRef>(NSIntegerName) 695176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines .Case("int8_t", "uint8_t") 696176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines .Case("int16_t", "uint16_t") 697176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines .Case("int32_t", "uint32_t") 698176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines .Case("NSInteger", "NSUInteger") 699176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines .Case("int64_t", "uint64_t") 700176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines .Default(NSIntegerName); 701176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return UnsignedName; 702176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines} 703176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 70444b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanianstatic bool rewriteToNSEnumDecl(const EnumDecl *EnumDcl, 70544b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian const TypedefDecl *TypedefDcl, 7069f9e54390c255587b009d912007b139432ab7bdcFariborz Jahanian const NSAPI &NS, edit::Commit &commit, 707176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines StringRef NSIntegerName, 708c9820ebfeff30598ebd7369c5daf5bde10df934bFariborz Jahanian bool NSOptions) { 709c9820ebfeff30598ebd7369c5daf5bde10df934bFariborz Jahanian std::string ClassString; 710176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (NSOptions) { 711176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines ClassString = "typedef NS_OPTIONS("; 712176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines ClassString += GetUnsignedName(NSIntegerName); 713176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 714176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines else { 715176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines ClassString = "typedef NS_ENUM("; 716176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines ClassString += NSIntegerName; 717176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines } 718176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines ClassString += ", "; 719c9820ebfeff30598ebd7369c5daf5bde10df934bFariborz Jahanian 72044b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian ClassString += TypedefDcl->getIdentifier()->getName(); 72144b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian ClassString += ')'; 72244b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian SourceRange R(EnumDcl->getLocStart(), EnumDcl->getLocStart()); 72344b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian commit.replace(R, ClassString); 724b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian SourceLocation EndOfEnumDclLoc = EnumDcl->getLocEnd(); 725b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian EndOfEnumDclLoc = trans::findSemiAfterLocation(EndOfEnumDclLoc, 726b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian NS.getASTContext(), /*IsDecl*/true); 727a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar if (EndOfEnumDclLoc.isValid()) { 728b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian SourceRange EnumDclRange(EnumDcl->getLocStart(), EndOfEnumDclLoc); 729b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian commit.insertFromRange(TypedefDcl->getLocStart(), EnumDclRange); 730b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian } 731b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian else 732b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian return false; 733b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian 734b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian SourceLocation EndTypedefDclLoc = TypedefDcl->getLocEnd(); 735b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian EndTypedefDclLoc = trans::findSemiAfterLocation(EndTypedefDclLoc, 736b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian NS.getASTContext(), /*IsDecl*/true); 737a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar if (EndTypedefDclLoc.isValid()) { 738b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian SourceRange TDRange(TypedefDcl->getLocStart(), EndTypedefDclLoc); 739b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian commit.remove(TDRange); 740b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian } 741b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian else 742b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian return false; 743b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian 744b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian EndOfEnumDclLoc = trans::findLocationAfterSemi(EnumDcl->getLocEnd(), NS.getASTContext(), 7451f9a09d4e50c3e8e622292350823eef776b93e3dFariborz Jahanian /*IsDecl*/true); 746a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar if (EndOfEnumDclLoc.isValid()) { 747b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian SourceLocation BeginOfEnumDclLoc = EnumDcl->getLocStart(); 748651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // FIXME. This assumes that enum decl; is immediately preceded by eoln. 749b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian // It is trying to remove the enum decl. lines entirely. 750b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian BeginOfEnumDclLoc = BeginOfEnumDclLoc.getLocWithOffset(-1); 751b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian commit.remove(SourceRange(BeginOfEnumDclLoc, EndOfEnumDclLoc)); 75244b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian return true; 75344b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian } 75444b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian return false; 75544b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian} 75644b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian 7570e2c34f92f00628d48968dfea096d36381f494cbStephen Hinesstatic void rewriteToNSMacroDecl(ASTContext &Ctx, 7580e2c34f92f00628d48968dfea096d36381f494cbStephen Hines const EnumDecl *EnumDcl, 759faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian const TypedefDecl *TypedefDcl, 760e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian const NSAPI &NS, edit::Commit &commit, 761e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian bool IsNSIntegerType) { 7623ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar QualType DesignatedEnumType = EnumDcl->getIntegerType(); 7633ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar assert(!DesignatedEnumType.isNull() 7640e2c34f92f00628d48968dfea096d36381f494cbStephen Hines && "rewriteToNSMacroDecl - underlying enum type is null"); 7650e2c34f92f00628d48968dfea096d36381f494cbStephen Hines 7660e2c34f92f00628d48968dfea096d36381f494cbStephen Hines PrintingPolicy Policy(Ctx.getPrintingPolicy()); 7673ea9e33ea25e0c2b12db56418ba3f994eb662c04Pirama Arumuga Nainar std::string TypeString = DesignatedEnumType.getAsString(Policy); 7680e2c34f92f00628d48968dfea096d36381f494cbStephen Hines std::string ClassString = IsNSIntegerType ? "NS_ENUM(" : "NS_OPTIONS("; 7690e2c34f92f00628d48968dfea096d36381f494cbStephen Hines ClassString += TypeString; 7700e2c34f92f00628d48968dfea096d36381f494cbStephen Hines ClassString += ", "; 7710e2c34f92f00628d48968dfea096d36381f494cbStephen Hines 772faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian ClassString += TypedefDcl->getIdentifier()->getName(); 773faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian ClassString += ')'; 7740e2c34f92f00628d48968dfea096d36381f494cbStephen Hines SourceLocation EndLoc; 7750e2c34f92f00628d48968dfea096d36381f494cbStephen Hines if (EnumDcl->getIntegerTypeSourceInfo()) { 7760e2c34f92f00628d48968dfea096d36381f494cbStephen Hines TypeSourceInfo *TSourceInfo = EnumDcl->getIntegerTypeSourceInfo(); 7770e2c34f92f00628d48968dfea096d36381f494cbStephen Hines TypeLoc TLoc = TSourceInfo->getTypeLoc(); 7780e2c34f92f00628d48968dfea096d36381f494cbStephen Hines EndLoc = TLoc.getLocEnd(); 7790e2c34f92f00628d48968dfea096d36381f494cbStephen Hines const char *lbrace = Ctx.getSourceManager().getCharacterData(EndLoc); 7800e2c34f92f00628d48968dfea096d36381f494cbStephen Hines unsigned count = 0; 7810e2c34f92f00628d48968dfea096d36381f494cbStephen Hines if (lbrace) 7820e2c34f92f00628d48968dfea096d36381f494cbStephen Hines while (lbrace[count] != '{') 7830e2c34f92f00628d48968dfea096d36381f494cbStephen Hines ++count; 7840e2c34f92f00628d48968dfea096d36381f494cbStephen Hines if (count > 0) 7850e2c34f92f00628d48968dfea096d36381f494cbStephen Hines EndLoc = EndLoc.getLocWithOffset(count-1); 7860e2c34f92f00628d48968dfea096d36381f494cbStephen Hines } 7870e2c34f92f00628d48968dfea096d36381f494cbStephen Hines else 7880e2c34f92f00628d48968dfea096d36381f494cbStephen Hines EndLoc = EnumDcl->getLocStart(); 7890e2c34f92f00628d48968dfea096d36381f494cbStephen Hines SourceRange R(EnumDcl->getLocStart(), EndLoc); 790faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian commit.replace(R, ClassString); 791176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines // This is to remove spaces between '}' and typedef name. 792176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines SourceLocation StartTypedefLoc = EnumDcl->getLocEnd(); 793176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines StartTypedefLoc = StartTypedefLoc.getLocWithOffset(+1); 794176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines SourceLocation EndTypedefLoc = TypedefDcl->getLocEnd(); 795176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 796176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines commit.remove(SourceRange(StartTypedefLoc, EndTypedefLoc)); 797faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian} 798faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian 799ad162e912db93be9494ba3ebc12994e51e0b0db2Fariborz Jahanianstatic bool UseNSOptionsMacro(Preprocessor &PP, ASTContext &Ctx, 800e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian const EnumDecl *EnumDcl) { 801e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian bool PowerOfTwo = true; 802ff89d06413ff79fb2314b9196fa2508e244159fcFariborz Jahanian bool AllHexdecimalEnumerator = true; 8030b5941c2a6ce99f0dc0dc8b64024eeabbbb6db1dFariborz Jahanian uint64_t MaxPowerOfTwoVal = 0; 804651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (auto Enumerator : EnumDcl->enumerators()) { 805e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian const Expr *InitExpr = Enumerator->getInitExpr(); 806e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian if (!InitExpr) { 807e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian PowerOfTwo = false; 808ff89d06413ff79fb2314b9196fa2508e244159fcFariborz Jahanian AllHexdecimalEnumerator = false; 809e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian continue; 810e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian } 811bb2405f293c79732748282538198e1d2d0f1b459Fariborz Jahanian InitExpr = InitExpr->IgnoreParenCasts(); 812e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(InitExpr)) 813e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian if (BO->isShiftOp() || BO->isBitwiseOp()) 814e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian return true; 815e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian 816e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian uint64_t EnumVal = Enumerator->getInitVal().getZExtValue(); 8170b5941c2a6ce99f0dc0dc8b64024eeabbbb6db1dFariborz Jahanian if (PowerOfTwo && EnumVal) { 8180b5941c2a6ce99f0dc0dc8b64024eeabbbb6db1dFariborz Jahanian if (!llvm::isPowerOf2_64(EnumVal)) 8190b5941c2a6ce99f0dc0dc8b64024eeabbbb6db1dFariborz Jahanian PowerOfTwo = false; 8200b5941c2a6ce99f0dc0dc8b64024eeabbbb6db1dFariborz Jahanian else if (EnumVal > MaxPowerOfTwoVal) 8210b5941c2a6ce99f0dc0dc8b64024eeabbbb6db1dFariborz Jahanian MaxPowerOfTwoVal = EnumVal; 8220b5941c2a6ce99f0dc0dc8b64024eeabbbb6db1dFariborz Jahanian } 823ff89d06413ff79fb2314b9196fa2508e244159fcFariborz Jahanian if (AllHexdecimalEnumerator && EnumVal) { 824ff89d06413ff79fb2314b9196fa2508e244159fcFariborz Jahanian bool FoundHexdecimalEnumerator = false; 825ad162e912db93be9494ba3ebc12994e51e0b0db2Fariborz Jahanian SourceLocation EndLoc = Enumerator->getLocEnd(); 826ad162e912db93be9494ba3ebc12994e51e0b0db2Fariborz Jahanian Token Tok; 827ad162e912db93be9494ba3ebc12994e51e0b0db2Fariborz Jahanian if (!PP.getRawToken(EndLoc, Tok, /*IgnoreWhiteSpace=*/true)) 828ad162e912db93be9494ba3ebc12994e51e0b0db2Fariborz Jahanian if (Tok.isLiteral() && Tok.getLength() > 2) { 829ad162e912db93be9494ba3ebc12994e51e0b0db2Fariborz Jahanian if (const char *StringLit = Tok.getLiteralData()) 830ad162e912db93be9494ba3ebc12994e51e0b0db2Fariborz Jahanian FoundHexdecimalEnumerator = 831ad162e912db93be9494ba3ebc12994e51e0b0db2Fariborz Jahanian (StringLit[0] == '0' && (toLowercase(StringLit[1]) == 'x')); 832ad162e912db93be9494ba3ebc12994e51e0b0db2Fariborz Jahanian } 833ff89d06413ff79fb2314b9196fa2508e244159fcFariborz Jahanian if (!FoundHexdecimalEnumerator) 834ff89d06413ff79fb2314b9196fa2508e244159fcFariborz Jahanian AllHexdecimalEnumerator = false; 835ad162e912db93be9494ba3ebc12994e51e0b0db2Fariborz Jahanian } 836e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian } 837ff89d06413ff79fb2314b9196fa2508e244159fcFariborz Jahanian return AllHexdecimalEnumerator || (PowerOfTwo && (MaxPowerOfTwoVal > 2)); 838e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian} 839e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian 84072685630b693c0ba6050875128ff6bb18107ba2fFariborz Jahanianvoid ObjCMigrateASTConsumer::migrateProtocolConformance(ASTContext &Ctx, 8417556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian const ObjCImplementationDecl *ImpDecl) { 8427556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian const ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface(); 843641645f00c22e1f55794537a43646214402e99a1Fariborz Jahanian if (!IDecl || ObjCProtocolDecls.empty() || IDecl->isDeprecated()) 8447556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian return; 8457556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian // Find all implicit conforming protocols for this class 8467556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian // and make them explicit. 8477556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian llvm::SmallPtrSet<ObjCProtocolDecl *, 8> ExplicitProtocols; 8487556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian Ctx.CollectInheritedProtocols(IDecl, ExplicitProtocols); 849e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian llvm::SmallVector<ObjCProtocolDecl *, 8> PotentialImplicitProtocols; 8507556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian 851176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines for (ObjCProtocolDecl *ProtDecl : ObjCProtocolDecls) 852176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (!ExplicitProtocols.count(ProtDecl)) 853176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines PotentialImplicitProtocols.push_back(ProtDecl); 8547556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian 8557556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian if (PotentialImplicitProtocols.empty()) 8567556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian return; 857e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian 858e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian // go through list of non-optional methods and properties in each protocol 859e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian // in the PotentialImplicitProtocols list. If class implements every one of the 860e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian // methods and properties, then this class conforms to this protocol. 861e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian llvm::SmallVector<ObjCProtocolDecl*, 8> ConformingProtocols; 862e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian for (unsigned i = 0, e = PotentialImplicitProtocols.size(); i != e; i++) 863ad4aaf11897cc5e9d443b0a80114daacf385f6dfFariborz Jahanian if (ClassImplementsAllMethodsAndProperties(Ctx, ImpDecl, IDecl, 864e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian PotentialImplicitProtocols[i])) 865e99b37c8f271814ba63046bbde9af0c68e7a26c9Fariborz Jahanian ConformingProtocols.push_back(PotentialImplicitProtocols[i]); 8668c355831ac3c9e8c12b23ca69b7587dcbd0439efFariborz Jahanian 8678c355831ac3c9e8c12b23ca69b7587dcbd0439efFariborz Jahanian if (ConformingProtocols.empty()) 8688c355831ac3c9e8c12b23ca69b7587dcbd0439efFariborz Jahanian return; 869e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian 870e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian // Further reduce number of conforming protocols. If protocol P1 is in the list 871e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian // protocol P2 (P2<P1>), No need to include P1. 872e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian llvm::SmallVector<ObjCProtocolDecl*, 8> MinimalConformingProtocols; 873e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) { 874e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian bool DropIt = false; 875e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian ObjCProtocolDecl *TargetPDecl = ConformingProtocols[i]; 876e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian for (unsigned i1 = 0, e1 = ConformingProtocols.size(); i1 != e1; i1++) { 877e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian ObjCProtocolDecl *PDecl = ConformingProtocols[i1]; 878e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian if (PDecl == TargetPDecl) 879e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian continue; 880e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian if (PDecl->lookupProtocolNamed( 881e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian TargetPDecl->getDeclName().getAsIdentifierInfo())) { 882e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian DropIt = true; 883e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian break; 884e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian } 885e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian } 886e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian if (!DropIt) 887e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian MinimalConformingProtocols.push_back(TargetPDecl); 888e8280188f7245e479418a716c3959f66b48ef64aFariborz Jahanian } 889651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (MinimalConformingProtocols.empty()) 890651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return; 8918c355831ac3c9e8c12b23ca69b7587dcbd0439efFariborz Jahanian edit::Commit commit(*Editor); 89244b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian rewriteToObjCInterfaceDecl(IDecl, MinimalConformingProtocols, 89344b41b12a44d74341fe7d241bfdf57847b728a62Fariborz Jahanian *NSAPIObj, commit); 8948c355831ac3c9e8c12b23ca69b7587dcbd0439efFariborz Jahanian Editor->commit(commit); 8957556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian} 8967556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian 897b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanianvoid ObjCMigrateASTConsumer::CacheObjCNSIntegerTypedefed( 898b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian const TypedefDecl *TypedefDcl) { 899b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian 900b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian QualType qt = TypedefDcl->getTypeSourceInfo()->getType(); 901b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian if (NSAPIObj->isObjCNSIntegerType(qt)) 902b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian NSIntegerTypedefed = TypedefDcl; 903b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian else if (NSAPIObj->isObjCNSUIntegerType(qt)) 904b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian NSUIntegerTypedefed = TypedefDcl; 905b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian} 906b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian 907d2dab64a438b7b8d57f8a10883e107d2bc0988edFariborz Jahanianbool ObjCMigrateASTConsumer::migrateNSEnumDecl(ASTContext &Ctx, 908bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian const EnumDecl *EnumDcl, 909bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian const TypedefDecl *TypedefDcl) { 910bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian if (!EnumDcl->isCompleteDefinition() || EnumDcl->getIdentifier() || 9110e2c34f92f00628d48968dfea096d36381f494cbStephen Hines EnumDcl->isDeprecated()) 912b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian return false; 913b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian if (!TypedefDcl) { 914b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian if (NSIntegerTypedefed) { 915b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian TypedefDcl = NSIntegerTypedefed; 9166bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines NSIntegerTypedefed = nullptr; 917b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian } 918b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian else if (NSUIntegerTypedefed) { 919b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian TypedefDcl = NSUIntegerTypedefed; 9206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines NSUIntegerTypedefed = nullptr; 921b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian } 922b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian else 923b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian return false; 924e909a720149ba5025209096fb9ed17e0162c8873Argyrios Kyrtzidis FileID FileIdOfTypedefDcl = 925e909a720149ba5025209096fb9ed17e0162c8873Argyrios Kyrtzidis PP.getSourceManager().getFileID(TypedefDcl->getLocation()); 926e909a720149ba5025209096fb9ed17e0162c8873Argyrios Kyrtzidis FileID FileIdOfEnumDcl = 927e909a720149ba5025209096fb9ed17e0162c8873Argyrios Kyrtzidis PP.getSourceManager().getFileID(EnumDcl->getLocation()); 928b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian if (FileIdOfTypedefDcl != FileIdOfEnumDcl) 929b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian return false; 930b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian } 931b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian if (TypedefDcl->isDeprecated()) 932d2dab64a438b7b8d57f8a10883e107d2bc0988edFariborz Jahanian return false; 933bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian 934bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian QualType qt = TypedefDcl->getTypeSourceInfo()->getType(); 935176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines StringRef NSIntegerName = NSAPIObj->GetNSIntegralKind(qt); 936e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian 937176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (NSIntegerName.empty()) { 938faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian // Also check for typedef enum {...} TD; 939faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian if (const EnumType *EnumTy = qt->getAs<EnumType>()) { 940faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian if (EnumTy->getDecl() == EnumDcl) { 941ad162e912db93be9494ba3ebc12994e51e0b0db2Fariborz Jahanian bool NSOptions = UseNSOptionsMacro(PP, Ctx, EnumDcl); 942176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (!InsertFoundation(Ctx, TypedefDcl->getLocStart())) 943d2dab64a438b7b8d57f8a10883e107d2bc0988edFariborz Jahanian return false; 944faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian edit::Commit commit(*Editor); 9450e2c34f92f00628d48968dfea096d36381f494cbStephen Hines rewriteToNSMacroDecl(Ctx, EnumDcl, TypedefDcl, *NSAPIObj, commit, !NSOptions); 946faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian Editor->commit(commit); 947f98f12f5f565a914d8996d881f53253f95a2db00Fariborz Jahanian return true; 948faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian } 949faae53d1cec325140a548c8e9ff647b7edb43702Fariborz Jahanian } 950d2dab64a438b7b8d57f8a10883e107d2bc0988edFariborz Jahanian return false; 951e3069e231eeeafeaef6078bc585c82dc6a1830e2Fariborz Jahanian } 952bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian 953c9820ebfeff30598ebd7369c5daf5bde10df934bFariborz Jahanian // We may still use NS_OPTIONS based on what we find in the enumertor list. 954c9820ebfeff30598ebd7369c5daf5bde10df934bFariborz Jahanian bool NSOptions = UseNSOptionsMacro(PP, Ctx, EnumDcl); 955176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (!InsertFoundation(Ctx, TypedefDcl->getLocStart())) 956d2dab64a438b7b8d57f8a10883e107d2bc0988edFariborz Jahanian return false; 957bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian edit::Commit commit(*Editor); 958b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian bool Res = rewriteToNSEnumDecl(EnumDcl, TypedefDcl, *NSAPIObj, 959176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines commit, NSIntegerName, NSOptions); 960bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian Editor->commit(commit); 961b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian return Res; 962bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian} 963bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian 9646bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesstatic void ReplaceWithInstancetype(ASTContext &Ctx, 9656bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const ObjCMigrateASTConsumer &ASTC, 966f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian ObjCMethodDecl *OM) { 9676bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (OM->getReturnType() == Ctx.getObjCInstanceType()) 9686bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return; // already has instancetype. 9696bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 970f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian SourceRange R; 971f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian std::string ClassString; 972651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (TypeSourceInfo *TSInfo = OM->getReturnTypeSourceInfo()) { 973f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian TypeLoc TL = TSInfo->getTypeLoc(); 974f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian R = SourceRange(TL.getBeginLoc(), TL.getEndLoc()); 975f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian ClassString = "instancetype"; 976f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian } 977f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian else { 978f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian R = SourceRange(OM->getLocStart(), OM->getLocStart()); 979f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian ClassString = OM->isInstanceMethod() ? '-' : '+'; 980f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian ClassString += " (instancetype)"; 981f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian } 982f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian edit::Commit commit(*ASTC.Editor); 983f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian commit.replace(R, ClassString); 984f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian ASTC.Editor->commit(commit); 985f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian} 986f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian 9879fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanianstatic void ReplaceWithClasstype(const ObjCMigrateASTConsumer &ASTC, 9889fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian ObjCMethodDecl *OM) { 9899fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian ObjCInterfaceDecl *IDecl = OM->getClassInterface(); 9909fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian SourceRange R; 9919fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian std::string ClassString; 992651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (TypeSourceInfo *TSInfo = OM->getReturnTypeSourceInfo()) { 9939fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian TypeLoc TL = TSInfo->getTypeLoc(); 9949fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian R = SourceRange(TL.getBeginLoc(), TL.getEndLoc()); { 9959fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian ClassString = IDecl->getName(); 9969fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian ClassString += "*"; 9979fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian } 9989fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian } 9999fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian else { 10009fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian R = SourceRange(OM->getLocStart(), OM->getLocStart()); 10019fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian ClassString = "+ ("; 10029fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian ClassString += IDecl->getName(); ClassString += "*)"; 10039fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian } 10049fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian edit::Commit commit(*ASTC.Editor); 10059fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian commit.replace(R, ClassString); 10069fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian ASTC.Editor->commit(commit); 10079fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian} 10089fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian 100926cf046ff3a2d24ff3e2c3757599976b644a06daFariborz Jahanianvoid ObjCMigrateASTConsumer::migrateMethodInstanceType(ASTContext &Ctx, 101026cf046ff3a2d24ff3e2c3757599976b644a06daFariborz Jahanian ObjCContainerDecl *CDecl, 101126cf046ff3a2d24ff3e2c3757599976b644a06daFariborz Jahanian ObjCMethodDecl *OM) { 101211638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian ObjCInstanceTypeFamily OIT_Family = 101311638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian Selector::getInstTypeMethodFamily(OM->getSelector()); 10148d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian 101565f1a4c931bc17e51c751a5e9c6a71a9e52d5b8cFariborz Jahanian std::string ClassName; 1016211b4a2b2260ba5a3150f2b8d47f569e9773b1d3Fariborz Jahanian switch (OIT_Family) { 10178d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian case OIT_None: 10188d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian migrateFactoryMethod(Ctx, CDecl, OM); 10198d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian return; 10203c6e5ce3776eaddaf4bcdf5da6c00ec4e6829d83Fariborz Jahanian case OIT_Array: 10213c6e5ce3776eaddaf4bcdf5da6c00ec4e6829d83Fariborz Jahanian ClassName = "NSArray"; 10223c6e5ce3776eaddaf4bcdf5da6c00ec4e6829d83Fariborz Jahanian break; 10233c6e5ce3776eaddaf4bcdf5da6c00ec4e6829d83Fariborz Jahanian case OIT_Dictionary: 10243c6e5ce3776eaddaf4bcdf5da6c00ec4e6829d83Fariborz Jahanian ClassName = "NSDictionary"; 10253c6e5ce3776eaddaf4bcdf5da6c00ec4e6829d83Fariborz Jahanian break; 10268d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian case OIT_Singleton: 10278d3794e06a63578093bd71c3c2520bd01e6197a3Fariborz Jahanian migrateFactoryMethod(Ctx, CDecl, OM, OIT_Singleton); 1028211b4a2b2260ba5a3150f2b8d47f569e9773b1d3Fariborz Jahanian return; 1029a346eb1188419d3f1698092edfbd66890b74163cFariborz Jahanian case OIT_Init: 1030651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (OM->getReturnType()->isObjCIdType()) 10316bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ReplaceWithInstancetype(Ctx, *this, OM); 1032a346eb1188419d3f1698092edfbd66890b74163cFariborz Jahanian return; 10339fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian case OIT_ReturnsSelf: 10349fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian migrateFactoryMethod(Ctx, CDecl, OM, OIT_ReturnsSelf); 10359fcbd5e55a8029a0ca8a5d64457278ec716a8705Fariborz Jahanian return; 1036211b4a2b2260ba5a3150f2b8d47f569e9773b1d3Fariborz Jahanian } 1037651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!OM->getReturnType()->isObjCIdType()) 103811638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian return; 103911638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian 104011638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl); 104111638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian if (!IDecl) { 104211638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) 104311638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian IDecl = CatDecl->getClassInterface(); 104411638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian else if (ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(CDecl)) 104511638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian IDecl = ImpDecl->getClassInterface(); 104611638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian } 104765f1a4c931bc17e51c751a5e9c6a71a9e52d5b8cFariborz Jahanian if (!IDecl || 1048f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian !IDecl->lookupInheritedClass(&Ctx.Idents.get(ClassName))) { 1049f647b69147c6e640bbccf501783fafc495bbefb2Fariborz Jahanian migrateFactoryMethod(Ctx, CDecl, OM); 105011638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian return; 1051cd683986e991f0e60afd6bc6f336cfc1fd844193Rafael Espindola } 10526bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ReplaceWithInstancetype(Ctx, *this, OM); 105311638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian} 105411638f7b922aa0182ab2028ec819001ed2fe8085Fariborz Jahanian 10558a6ad2a21dcb654db25cf66408466d2e7a93e09cFariborz Jahanianstatic bool TypeIsInnerPointer(QualType T) { 10568a6ad2a21dcb654db25cf66408466d2e7a93e09cFariborz Jahanian if (!T->isAnyPointerType()) 10578a6ad2a21dcb654db25cf66408466d2e7a93e09cFariborz Jahanian return false; 10588a6ad2a21dcb654db25cf66408466d2e7a93e09cFariborz Jahanian if (T->isObjCObjectPointerType() || T->isObjCBuiltinType() || 10590d4e06872de210a9f9ed89781ba606ea22fb61b8Fariborz Jahanian T->isBlockPointerType() || T->isFunctionPointerType() || 10600d4e06872de210a9f9ed89781ba606ea22fb61b8Fariborz Jahanian ento::coreFoundation::isCFObjectRef(T)) 10618a6ad2a21dcb654db25cf66408466d2e7a93e09cFariborz Jahanian return false; 1062c72b4b396a9b87cf9cdb9958308d82fd32bdb846Fariborz Jahanian // Also, typedef-of-pointer-to-incomplete-struct is something that we assume 1063c72b4b396a9b87cf9cdb9958308d82fd32bdb846Fariborz Jahanian // is not an innter pointer type. 1064c72b4b396a9b87cf9cdb9958308d82fd32bdb846Fariborz Jahanian QualType OrigT = T; 1065c72b4b396a9b87cf9cdb9958308d82fd32bdb846Fariborz Jahanian while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr())) 1066c72b4b396a9b87cf9cdb9958308d82fd32bdb846Fariborz Jahanian T = TD->getDecl()->getUnderlyingType(); 1067c72b4b396a9b87cf9cdb9958308d82fd32bdb846Fariborz Jahanian if (OrigT == T || !T->isPointerType()) 1068c72b4b396a9b87cf9cdb9958308d82fd32bdb846Fariborz Jahanian return true; 1069c72b4b396a9b87cf9cdb9958308d82fd32bdb846Fariborz Jahanian const PointerType* PT = T->getAs<PointerType>(); 1070c72b4b396a9b87cf9cdb9958308d82fd32bdb846Fariborz Jahanian QualType UPointeeT = PT->getPointeeType().getUnqualifiedType(); 1071c72b4b396a9b87cf9cdb9958308d82fd32bdb846Fariborz Jahanian if (UPointeeT->isRecordType()) { 1072c72b4b396a9b87cf9cdb9958308d82fd32bdb846Fariborz Jahanian const RecordType *RecordTy = UPointeeT->getAs<RecordType>(); 1073c72b4b396a9b87cf9cdb9958308d82fd32bdb846Fariborz Jahanian if (!RecordTy->getDecl()->isCompleteDefinition()) 1074c72b4b396a9b87cf9cdb9958308d82fd32bdb846Fariborz Jahanian return false; 1075c72b4b396a9b87cf9cdb9958308d82fd32bdb846Fariborz Jahanian } 10768a6ad2a21dcb654db25cf66408466d2e7a93e09cFariborz Jahanian return true; 10778a6ad2a21dcb654db25cf66408466d2e7a93e09cFariborz Jahanian} 10788a6ad2a21dcb654db25cf66408466d2e7a93e09cFariborz Jahanian 1079257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian/// \brief Check whether the two versions match. 1080257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanianstatic bool versionsMatch(const VersionTuple &X, const VersionTuple &Y) { 1081257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian return (X == Y); 1082257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian} 1083257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian 1084257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian/// AvailabilityAttrsMatch - This routine checks that if comparing two 1085257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian/// availability attributes, all their components match. It returns 1086257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian/// true, if not dealing with availability or when all components of 1087257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian/// availability attributes match. This routine is only called when 1088257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian/// the attributes are of the same kind. 1089257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanianstatic bool AvailabilityAttrsMatch(Attr *At1, Attr *At2) { 1090257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian const AvailabilityAttr *AA1 = dyn_cast<AvailabilityAttr>(At1); 1091257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian if (!AA1) 1092f9d38c08bc77da4ebd67fdc7cb4f42da671f7d2bFariborz Jahanian return true; 1093257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian const AvailabilityAttr *AA2 = dyn_cast<AvailabilityAttr>(At2); 1094f9d38c08bc77da4ebd67fdc7cb4f42da671f7d2bFariborz Jahanian 1095257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian VersionTuple Introduced1 = AA1->getIntroduced(); 1096257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian VersionTuple Deprecated1 = AA1->getDeprecated(); 1097257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian VersionTuple Obsoleted1 = AA1->getObsoleted(); 1098257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian bool IsUnavailable1 = AA1->getUnavailable(); 1099257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian VersionTuple Introduced2 = AA2->getIntroduced(); 1100257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian VersionTuple Deprecated2 = AA2->getDeprecated(); 1101257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian VersionTuple Obsoleted2 = AA2->getObsoleted(); 1102257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian bool IsUnavailable2 = AA2->getUnavailable(); 1103257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian return (versionsMatch(Introduced1, Introduced2) && 1104257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian versionsMatch(Deprecated1, Deprecated2) && 1105257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian versionsMatch(Obsoleted1, Obsoleted2) && 1106257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian IsUnavailable1 == IsUnavailable2); 1107257ddb2b4721e71749174ddaf03c6692df9dd346Fariborz Jahanian 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 Jahanian 1513a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz JahanianObjCMigrateASTConsumer::CF_BRIDGING_KIND 1514a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian ObjCMigrateASTConsumer::migrateAddFunctionAnnotation( 1515a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian ASTContext &Ctx, 1516a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian const FunctionDecl *FuncDecl) { 1517a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian if (FuncDecl->hasBody()) 1518a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian return CF_BRIDGING_NONE; 1519a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian 1520a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian CallEffects CE = CallEffects::getEffect(FuncDecl); 1521651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool FuncIsReturnAnnotated = (FuncDecl->hasAttr<CFReturnsRetainedAttr>() || 1522651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FuncDecl->hasAttr<CFReturnsNotRetainedAttr>() || 1523651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FuncDecl->hasAttr<NSReturnsRetainedAttr>() || 1524651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FuncDecl->hasAttr<NSReturnsNotRetainedAttr>() || 1525651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FuncDecl->hasAttr<NSReturnsAutoreleasedAttr>()); 1526a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian 1527a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar // Trivial case of when function is annotated and has no argument. 1528a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian if (FuncIsReturnAnnotated && FuncDecl->getNumParams() == 0) 1529a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian return CF_BRIDGING_NONE; 1530a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian 1531a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian bool ReturnCFAudited = false; 1532a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian if (!FuncIsReturnAnnotated) { 1533a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian RetEffect Ret = CE.getReturnValue(); 1534a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian if (Ret.getObjKind() == RetEffect::CF && 15355f7ac67c84e7b9a04fa4c5065e384f928c8f812fFariborz Jahanian (Ret.isOwned() || Ret.notOwned())) 1536a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian ReturnCFAudited = true; 1537651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines else if (!AuditedType(FuncDecl->getReturnType())) 1538a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian return CF_BRIDGING_NONE; 1539269cca13cdafab34073158476de0391d1839ecd3Fariborz Jahanian } 1540a46c6c3baa0bb24987b44ac7a5543fa60e8b639eFariborz Jahanian 1541a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian // At this point result type is audited for potential inclusion. 15426cb33a4e9e8298dfa4a8aa33ccc34ce68580f234Fariborz Jahanian // Now, how about argument types. 1543c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ArrayRef<ArgEffect> AEArgs = CE.getArgs(); 15446cb33a4e9e8298dfa4a8aa33ccc34ce68580f234Fariborz Jahanian unsigned i = 0; 1545a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian bool ArgCFAudited = false; 15466cb33a4e9e8298dfa4a8aa33ccc34ce68580f234Fariborz Jahanian for (FunctionDecl::param_const_iterator pi = FuncDecl->param_begin(), 15476cb33a4e9e8298dfa4a8aa33ccc34ce68580f234Fariborz Jahanian pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) { 1548a178593335e12761d4362eab0eff0c12ad081635Fariborz Jahanian const ParmVarDecl *pd = *pi; 15496cb33a4e9e8298dfa4a8aa33ccc34ce68580f234Fariborz Jahanian ArgEffect AE = AEArgs[i]; 1550a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian if (AE == DecRef /*CFConsumed annotated*/ || AE == IncRef) { 1551651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (AE == DecRef && !pd->hasAttr<CFConsumedAttr>()) 1552a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian ArgCFAudited = true; 1553a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian else if (AE == IncRef) 1554a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian ArgCFAudited = true; 1555a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian } 1556a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian else { 1557a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian QualType AT = pd->getType(); 1558a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian if (!AuditedType(AT)) { 1559c1cc488c3cf9ce7f7b7e211e891e2be7391e0e5aFariborz Jahanian AddCFAnnotations(Ctx, CE, FuncDecl, FuncIsReturnAnnotated); 1560a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian return CF_BRIDGING_NONE; 1561a178593335e12761d4362eab0eff0c12ad081635Fariborz Jahanian } 1562a46c6c3baa0bb24987b44ac7a5543fa60e8b639eFariborz Jahanian } 1563269cca13cdafab34073158476de0391d1839ecd3Fariborz Jahanian } 1564a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian if (ReturnCFAudited || ArgCFAudited) 1565a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian return CF_BRIDGING_ENABLE; 1566a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian 1567a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian return CF_BRIDGING_MAY_INCLUDE; 156846f4fd5938b0ff4ebbb83ba1df225f73d640613dFariborz Jahanian} 156946f4fd5938b0ff4ebbb83ba1df225f73d640613dFariborz Jahanian 1570d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanianvoid ObjCMigrateASTConsumer::migrateARCSafeAnnotation(ASTContext &Ctx, 1571d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian ObjCContainerDecl *CDecl) { 1572641645f00c22e1f55794537a43646214402e99a1Fariborz Jahanian if (!isa<ObjCInterfaceDecl>(CDecl) || CDecl->isDeprecated()) 1573d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian return; 1574d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian 1575d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian // migrate methods which can have instancetype as their result type. 1576651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto *Method : CDecl->methods()) 1577d76941102f17d5f4e88ef027151c20c95b745c8bFariborz Jahanian migrateCFAnnotation(Ctx, Method); 1578d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian} 1579d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian 1580a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanianvoid ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx, 1581a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian const CallEffects &CE, 1582c1cc488c3cf9ce7f7b7e211e891e2be7391e0e5aFariborz Jahanian const ObjCMethodDecl *MethodDecl, 1583c1cc488c3cf9ce7f7b7e211e891e2be7391e0e5aFariborz Jahanian bool ResultAnnotated) { 1584a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian // Annotate function. 1585c1cc488c3cf9ce7f7b7e211e891e2be7391e0e5aFariborz Jahanian if (!ResultAnnotated) { 1586d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian RetEffect Ret = CE.getReturnValue(); 15876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const char *AnnotationString = nullptr; 15884afe57965e19d9c9ba8070ac9901ed8a20e20fceFariborz Jahanian if (Ret.getObjKind() == RetEffect::CF) { 1589b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar if (Ret.isOwned() && NSAPIObj->isMacroDefined("CF_RETURNS_RETAINED")) 1590d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian AnnotationString = " CF_RETURNS_RETAINED"; 15914afe57965e19d9c9ba8070ac9901ed8a20e20fceFariborz Jahanian else if (Ret.notOwned() && 1592b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar NSAPIObj->isMacroDefined("CF_RETURNS_NOT_RETAINED")) 1593d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian AnnotationString = " CF_RETURNS_NOT_RETAINED"; 1594d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian } 15954afe57965e19d9c9ba8070ac9901ed8a20e20fceFariborz Jahanian else if (Ret.getObjKind() == RetEffect::ObjC) { 15967fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian ObjCMethodFamily OMF = MethodDecl->getMethodFamily(); 15977fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian switch (OMF) { 15987fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian case clang::OMF_alloc: 15997fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian case clang::OMF_new: 16007fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian case clang::OMF_copy: 16017fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian case clang::OMF_init: 16027fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian case clang::OMF_mutableCopy: 16037fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian break; 16047fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian 16057fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian default: 1606b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar if (Ret.isOwned() && NSAPIObj->isMacroDefined("NS_RETURNS_RETAINED")) 16077fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian AnnotationString = " NS_RETURNS_RETAINED"; 16087fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian break; 16097fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian } 16104afe57965e19d9c9ba8070ac9901ed8a20e20fceFariborz Jahanian } 16114afe57965e19d9c9ba8070ac9901ed8a20e20fceFariborz Jahanian 1612d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian if (AnnotationString) { 1613d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian edit::Commit commit(*Editor); 1614d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian commit.insertBefore(MethodDecl->getLocEnd(), AnnotationString); 1615d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian Editor->commit(commit); 1616d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian } 1617a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian } 1618c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ArrayRef<ArgEffect> AEArgs = CE.getArgs(); 1619a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian unsigned i = 0; 1620a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian for (ObjCMethodDecl::param_const_iterator pi = MethodDecl->param_begin(), 1621a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) { 1622a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian const ParmVarDecl *pd = *pi; 1623a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian ArgEffect AE = AEArgs[i]; 1624651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (AE == DecRef && !pd->hasAttr<CFConsumedAttr>() && 1625b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar NSAPIObj->isMacroDefined("CF_CONSUMED")) { 1626a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian edit::Commit commit(*Editor); 1627a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian commit.insertBefore(pd->getLocation(), "CF_CONSUMED "); 1628a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian Editor->commit(commit); 1629a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian } 1630a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian } 1631a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian} 1632a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian 16335f7ac67c84e7b9a04fa4c5065e384f928c8f812fFariborz Jahanianvoid ObjCMigrateASTConsumer::migrateAddMethodAnnotation( 1634a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian ASTContext &Ctx, 1635a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian const ObjCMethodDecl *MethodDecl) { 16364afe57965e19d9c9ba8070ac9901ed8a20e20fceFariborz Jahanian if (MethodDecl->hasBody() || MethodDecl->isImplicit()) 16375f7ac67c84e7b9a04fa4c5065e384f928c8f812fFariborz Jahanian return; 1638a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian 1639a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian CallEffects CE = CallEffects::getEffect(MethodDecl); 1640651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool MethodIsReturnAnnotated = (MethodDecl->hasAttr<CFReturnsRetainedAttr>() || 1641651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines MethodDecl->hasAttr<CFReturnsNotRetainedAttr>() || 1642651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines MethodDecl->hasAttr<NSReturnsRetainedAttr>() || 1643651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines MethodDecl->hasAttr<NSReturnsNotRetainedAttr>() || 1644651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines MethodDecl->hasAttr<NSReturnsAutoreleasedAttr>()); 1645b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar 1646b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar if (CE.getReceiver() == DecRefMsg && 1647651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines !MethodDecl->hasAttr<NSConsumesSelfAttr>() && 16487fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian MethodDecl->getMethodFamily() != OMF_init && 16497fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian MethodDecl->getMethodFamily() != OMF_release && 1650b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar NSAPIObj->isMacroDefined("NS_CONSUMES_SELF")) { 16517fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian edit::Commit commit(*Editor); 16527fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian commit.insertBefore(MethodDecl->getLocEnd(), " NS_CONSUMES_SELF"); 16537fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian Editor->commit(commit); 16547fd8fb3a513330c9e754a6eec162170d5a979859Fariborz Jahanian } 1655a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian 1656a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar // Trivial case of when function is annotated and has no argument. 1657a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian if (MethodIsReturnAnnotated && 1658a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian (MethodDecl->param_begin() == MethodDecl->param_end())) 16595f7ac67c84e7b9a04fa4c5065e384f928c8f812fFariborz Jahanian return; 1660a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian 1661a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian if (!MethodIsReturnAnnotated) { 1662a7f6a94c1bae840c51351cd37cc247ae75f8e649Fariborz Jahanian RetEffect Ret = CE.getReturnValue(); 16634afe57965e19d9c9ba8070ac9901ed8a20e20fceFariborz Jahanian if ((Ret.getObjKind() == RetEffect::CF || 16644afe57965e19d9c9ba8070ac9901ed8a20e20fceFariborz Jahanian Ret.getObjKind() == RetEffect::ObjC) && 16654afe57965e19d9c9ba8070ac9901ed8a20e20fceFariborz Jahanian (Ret.isOwned() || Ret.notOwned())) { 1666a7a2a24956a53541acad07583c92747044e5bb95Fariborz Jahanian AddCFAnnotations(Ctx, CE, MethodDecl, false); 1667a7a2a24956a53541acad07583c92747044e5bb95Fariborz Jahanian return; 1668651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } else if (!AuditedType(MethodDecl->getReturnType())) 16695f7ac67c84e7b9a04fa4c5065e384f928c8f812fFariborz Jahanian return; 1670d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian } 1671d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian 1672d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian // At this point result type is either annotated or audited. 1673d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian // Now, how about argument types. 1674c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines ArrayRef<ArgEffect> AEArgs = CE.getArgs(); 1675d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian unsigned i = 0; 1676d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian for (ObjCMethodDecl::param_const_iterator pi = MethodDecl->param_begin(), 1677d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) { 1678d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian const ParmVarDecl *pd = *pi; 1679d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian ArgEffect AE = AEArgs[i]; 1680651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if ((AE == DecRef && !pd->hasAttr<CFConsumedAttr>()) || AE == IncRef || 1681a7a2a24956a53541acad07583c92747044e5bb95Fariborz Jahanian !AuditedType(pd->getType())) { 1682a7a2a24956a53541acad07583c92747044e5bb95Fariborz Jahanian AddCFAnnotations(Ctx, CE, MethodDecl, MethodIsReturnAnnotated); 1683a7a2a24956a53541acad07583c92747044e5bb95Fariborz Jahanian return; 1684d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian } 1685d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian } 16865f7ac67c84e7b9a04fa4c5065e384f928c8f812fFariborz Jahanian return; 168746f4fd5938b0ff4ebbb83ba1df225f73d640613dFariborz Jahanian} 168846f4fd5938b0ff4ebbb83ba1df225f73d640613dFariborz Jahanian 168930660a898545416f0fea2d717f16f75640001e38Ted Kremeneknamespace { 1690651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesclass SuperInitChecker : public RecursiveASTVisitor<SuperInitChecker> { 1691651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinespublic: 1692651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool shouldVisitTemplateInstantiations() const { return false; } 1693651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool shouldWalkTypesOfTypeLocs() const { return false; } 1694651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1695651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool VisitObjCMessageExpr(ObjCMessageExpr *E) { 1696651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (E->getReceiverKind() == ObjCMessageExpr::SuperInstance) { 1697651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (E->getMethodFamily() == OMF_init) 1698651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return false; 1699651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1700651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return true; 1701651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1702651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}; 1703651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} // anonymous namespace 1704651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1705651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic bool hasSuperInitCall(const ObjCMethodDecl *MD) { 1706651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return !SuperInitChecker().TraverseStmt(MD->getBody()); 1707651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 1708651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1709651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesvoid ObjCMigrateASTConsumer::inferDesignatedInitializers( 1710651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ASTContext &Ctx, 1711651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const ObjCImplementationDecl *ImplD) { 1712651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1713651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const ObjCInterfaceDecl *IFace = ImplD->getClassInterface(); 1714651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!IFace || IFace->hasDesignatedInitializers()) 1715651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return; 1716b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar if (!NSAPIObj->isMacroDefined("NS_DESIGNATED_INITIALIZER")) 1717651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return; 1718651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1719651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto *MD : ImplD->instance_methods()) { 1720651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (MD->isDeprecated() || 1721651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines MD->getMethodFamily() != OMF_init || 1722651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines MD->isDesignatedInitializerForTheInterface()) 1723651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 1724651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const ObjCMethodDecl *IFaceM = IFace->getMethod(MD->getSelector(), 1725651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines /*isInstance=*/true); 1726651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!IFaceM) 1727651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 1728651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (hasSuperInitCall(MD)) { 1729651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines edit::Commit commit(*Editor); 1730651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines commit.insert(IFaceM->getLocEnd(), " NS_DESIGNATED_INITIALIZER"); 1731651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Editor->commit(commit); 1732651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1733651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1734651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 1735651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1736176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesbool ObjCMigrateASTConsumer::InsertFoundation(ASTContext &Ctx, 1737176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines SourceLocation Loc) { 1738176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (FoundationIncluded) 1739176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return true; 1740176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (Loc.isInvalid()) 1741176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return false; 1742176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines edit::Commit commit(*Editor); 1743176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (Ctx.getLangOpts().Modules) 1744176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines commit.insert(Loc, "#ifndef NS_ENUM\n@import Foundation;\n#endif\n"); 1745176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines else 1746176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines commit.insert(Loc, "#ifndef NS_ENUM\n#import <Foundation/Foundation.h>\n#endif\n"); 1747176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Editor->commit(commit); 1748176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines FoundationIncluded = true; 1749176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return true; 1750176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines} 1751176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 1752651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesnamespace { 175330660a898545416f0fea2d717f16f75640001e38Ted Kremenek 175430660a898545416f0fea2d717f16f75640001e38Ted Kremenekclass RewritesReceiver : public edit::EditsReceiver { 175530660a898545416f0fea2d717f16f75640001e38Ted Kremenek Rewriter &Rewrite; 175630660a898545416f0fea2d717f16f75640001e38Ted Kremenek 175730660a898545416f0fea2d717f16f75640001e38Ted Kremenekpublic: 175830660a898545416f0fea2d717f16f75640001e38Ted Kremenek RewritesReceiver(Rewriter &Rewrite) : Rewrite(Rewrite) { } 175930660a898545416f0fea2d717f16f75640001e38Ted Kremenek 1760651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void insert(SourceLocation loc, StringRef text) override { 176130660a898545416f0fea2d717f16f75640001e38Ted Kremenek Rewrite.InsertText(loc, text); 176230660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 1763651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void replace(CharSourceRange range, StringRef text) override { 176430660a898545416f0fea2d717f16f75640001e38Ted Kremenek Rewrite.ReplaceText(range.getBegin(), Rewrite.getRangeSize(range), text); 176530660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 176630660a898545416f0fea2d717f16f75640001e38Ted Kremenek}; 176730660a898545416f0fea2d717f16f75640001e38Ted Kremenek 1768651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesclass JSONEditWriter : public edit::EditsReceiver { 1769651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SourceManager &SourceMgr; 1770651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines llvm::raw_ostream &OS; 1771651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1772651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinespublic: 1773651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines JSONEditWriter(SourceManager &SM, llvm::raw_ostream &OS) 1774651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines : SourceMgr(SM), OS(OS) { 1775651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << "[\n"; 1776651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 177758878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar ~JSONEditWriter() override { OS << "]\n"; } 1778651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1779651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesprivate: 1780651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines struct EntryWriter { 1781651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SourceManager &SourceMgr; 1782651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines llvm::raw_ostream &OS; 1783651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1784651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines EntryWriter(SourceManager &SM, llvm::raw_ostream &OS) 1785651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines : SourceMgr(SM), OS(OS) { 1786651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " {\n"; 1787651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1788651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ~EntryWriter() { 1789651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " },\n"; 1790651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1791651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1792651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeLoc(SourceLocation Loc) { 1793651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FileID FID; 1794651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines unsigned Offset; 1795651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::tie(FID, Offset) = SourceMgr.getDecomposedLoc(Loc); 1796a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar assert(FID.isValid()); 1797651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SmallString<200> Path = 1798651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines StringRef(SourceMgr.getFileEntryForID(FID)->getName()); 1799651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines llvm::sys::fs::make_absolute(Path); 1800651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " \"file\": \""; 1801651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS.write_escaped(Path.str()) << "\",\n"; 1802651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " \"offset\": " << Offset << ",\n"; 1803651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1804651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1805651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeRemove(CharSourceRange Range) { 1806651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines assert(Range.isCharRange()); 1807651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::pair<FileID, unsigned> Begin = 1808651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SourceMgr.getDecomposedLoc(Range.getBegin()); 1809651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::pair<FileID, unsigned> End = 1810651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SourceMgr.getDecomposedLoc(Range.getEnd()); 1811651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines assert(Begin.first == End.first); 1812651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines assert(Begin.second <= End.second); 1813651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines unsigned Length = End.second - Begin.second; 1814651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1815651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " \"remove\": " << Length << ",\n"; 1816651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1817651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1818651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void writeText(StringRef Text) { 1819651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << " \"text\": \""; 1820651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS.write_escaped(Text) << "\",\n"; 1821651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1822651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines }; 1823651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1824651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void insert(SourceLocation Loc, StringRef Text) override { 1825651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines EntryWriter Writer(SourceMgr, OS); 1826651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Writer.writeLoc(Loc); 1827651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Writer.writeText(Text); 1828651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1829651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1830651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void replace(CharSourceRange Range, StringRef Text) override { 1831651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines EntryWriter Writer(SourceMgr, OS); 1832651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Writer.writeLoc(Range.getBegin()); 1833651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Writer.writeRemove(Range); 1834651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Writer.writeText(Text); 1835651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1836651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1837651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void remove(CharSourceRange Range) override { 1838651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines EntryWriter Writer(SourceMgr, OS); 1839651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Writer.writeLoc(Range.getBegin()); 1840651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Writer.writeRemove(Range); 1841651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1842651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}; 1843651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 184430660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 184530660a898545416f0fea2d717f16f75640001e38Ted Kremenek 184630660a898545416f0fea2d717f16f75640001e38Ted Kremenekvoid ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) { 1847baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian 1848baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian TranslationUnitDecl *TU = Ctx.getTranslationUnitDecl(); 1849081099d302b79d1746c7a39da14e3265971eb718Fariborz Jahanian if (ASTMigrateActions & FrontendOptions::ObjCMT_MigrateDecls) { 1850d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian for (DeclContext::decl_iterator D = TU->decls_begin(), DEnd = TU->decls_end(); 1851d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian D != DEnd; ++D) { 1852e909a720149ba5025209096fb9ed17e0162c8873Argyrios Kyrtzidis FileID FID = PP.getSourceManager().getFileID((*D)->getLocation()); 1853a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar if (FID.isValid()) 1854a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar if (FileId.isValid() && FileId != FID) { 1855b8941a15b6b5477a81c189614d0129070ac099f1Fariborz Jahanian if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) 1856b8941a15b6b5477a81c189614d0129070ac099f1Fariborz Jahanian AnnotateImplicitBridging(Ctx); 1857b8941a15b6b5477a81c189614d0129070ac099f1Fariborz Jahanian } 1858b8941a15b6b5477a81c189614d0129070ac099f1Fariborz Jahanian 1859d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian if (ObjCInterfaceDecl *CDecl = dyn_cast<ObjCInterfaceDecl>(*D)) 1860651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (canModify(CDecl)) 186158878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar migrateObjCContainerDecl(Ctx, CDecl); 18626d754e9a9d6591e8fc5eedc144cc70a7e539ba6fFariborz Jahanian if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(*D)) { 1863651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (canModify(CatDecl)) 186458878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar migrateObjCContainerDecl(Ctx, CatDecl); 18656d754e9a9d6591e8fc5eedc144cc70a7e539ba6fFariborz Jahanian } 186658878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(*D)) { 1867651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ObjCProtocolDecls.insert(PDecl->getCanonicalDecl()); 186858878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar if (canModify(PDecl)) 186958878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar migrateObjCContainerDecl(Ctx, PDecl); 187058878f85ab89b13e9eea4af3ccf055e42c557bc8Pirama Arumuga Nainar } 18717556853c60f3e2a3f43864d8ebe74ba5ac11e68eFariborz Jahanian else if (const ObjCImplementationDecl *ImpDecl = 1872b8941a15b6b5477a81c189614d0129070ac099f1Fariborz Jahanian dyn_cast<ObjCImplementationDecl>(*D)) { 1873651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if ((ASTMigrateActions & FrontendOptions::ObjCMT_ProtocolConformance) && 1874651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines canModify(ImpDecl)) 1875b8941a15b6b5477a81c189614d0129070ac099f1Fariborz Jahanian migrateProtocolConformance(Ctx, ImpDecl); 1876b8941a15b6b5477a81c189614d0129070ac099f1Fariborz Jahanian } 1877bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian else if (const EnumDecl *ED = dyn_cast<EnumDecl>(*D)) { 1878b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian if (!(ASTMigrateActions & FrontendOptions::ObjCMT_NsMacros)) 1879b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian continue; 1880651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!canModify(ED)) 1881651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 1882bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian DeclContext::decl_iterator N = D; 1883b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian if (++N != DEnd) { 1884b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian const TypedefDecl *TD = dyn_cast<TypedefDecl>(*N); 1885b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian if (migrateNSEnumDecl(Ctx, ED, TD) && TD) 1886b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian D++; 1887b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian } 1888b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian else 18896bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines migrateNSEnumDecl(Ctx, ED, /*TypedefDecl */nullptr); 1890d2dab64a438b7b8d57f8a10883e107d2bc0988edFariborz Jahanian } 1891d2dab64a438b7b8d57f8a10883e107d2bc0988edFariborz Jahanian else if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(*D)) { 1892d33884f1e2e3189ee2db75cc72d90ea854f6bc68Fariborz Jahanian if (!(ASTMigrateActions & FrontendOptions::ObjCMT_NsMacros)) 1893d33884f1e2e3189ee2db75cc72d90ea854f6bc68Fariborz Jahanian continue; 1894651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!canModify(TD)) 1895651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 1896d33884f1e2e3189ee2db75cc72d90ea854f6bc68Fariborz Jahanian DeclContext::decl_iterator N = D; 1897d33884f1e2e3189ee2db75cc72d90ea854f6bc68Fariborz Jahanian if (++N == DEnd) 1898d33884f1e2e3189ee2db75cc72d90ea854f6bc68Fariborz Jahanian continue; 1899d33884f1e2e3189ee2db75cc72d90ea854f6bc68Fariborz Jahanian if (const EnumDecl *ED = dyn_cast<EnumDecl>(*N)) { 1900b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian if (++N != DEnd) 1901d33884f1e2e3189ee2db75cc72d90ea854f6bc68Fariborz Jahanian if (const TypedefDecl *TDF = dyn_cast<TypedefDecl>(*N)) { 1902d33884f1e2e3189ee2db75cc72d90ea854f6bc68Fariborz Jahanian // prefer typedef-follows-enum to enum-follows-typedef pattern. 1903d33884f1e2e3189ee2db75cc72d90ea854f6bc68Fariborz Jahanian if (migrateNSEnumDecl(Ctx, ED, TDF)) { 1904d33884f1e2e3189ee2db75cc72d90ea854f6bc68Fariborz Jahanian ++D; ++D; 1905d33884f1e2e3189ee2db75cc72d90ea854f6bc68Fariborz Jahanian CacheObjCNSIntegerTypedefed(TD); 1906b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian continue; 1907b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian } 1908d2dab64a438b7b8d57f8a10883e107d2bc0988edFariborz Jahanian } 1909d33884f1e2e3189ee2db75cc72d90ea854f6bc68Fariborz Jahanian if (migrateNSEnumDecl(Ctx, ED, TD)) { 1910d33884f1e2e3189ee2db75cc72d90ea854f6bc68Fariborz Jahanian ++D; 1911d33884f1e2e3189ee2db75cc72d90ea854f6bc68Fariborz Jahanian continue; 1912d33884f1e2e3189ee2db75cc72d90ea854f6bc68Fariborz Jahanian } 1913b3c71facc346f70fe4958f766ab55bd537229195Fariborz Jahanian } 1914d33884f1e2e3189ee2db75cc72d90ea854f6bc68Fariborz Jahanian CacheObjCNSIntegerTypedefed(TD); 1915b8941a15b6b5477a81c189614d0129070ac099f1Fariborz Jahanian } 1916b8941a15b6b5477a81c189614d0129070ac099f1Fariborz Jahanian else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*D)) { 1917651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if ((ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) && 1918651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines canModify(FD)) 1919b8941a15b6b5477a81c189614d0129070ac099f1Fariborz Jahanian migrateCFAnnotation(Ctx, FD); 1920bbbb0fe4f466d3163fcbf0a64ebf0f5868833efbFariborz Jahanian } 1921086d565d2d3b8e72f95492d3a2cefd09e1718f2aFariborz Jahanian 1922d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian if (ObjCContainerDecl *CDecl = dyn_cast<ObjCContainerDecl>(*D)) { 1923651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool CanModify = canModify(CDecl); 1924d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian // migrate methods which can have instancetype as their result type. 1925651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if ((ASTMigrateActions & FrontendOptions::ObjCMT_Instancetype) && 1926651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CanModify) 1927b8941a15b6b5477a81c189614d0129070ac099f1Fariborz Jahanian migrateAllMethodInstaceType(Ctx, CDecl); 1928d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian // annotate methods with CF annotations. 1929651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if ((ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) && 1930651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CanModify) 1931b8941a15b6b5477a81c189614d0129070ac099f1Fariborz Jahanian migrateARCSafeAnnotation(Ctx, CDecl); 1932d173d7885b6e7b40f2342cbc5aaaaef9c3e6c33bFariborz Jahanian } 1933651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1934651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (const ObjCImplementationDecl * 1935651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ImplD = dyn_cast<ObjCImplementationDecl>(*D)) { 1936651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if ((ASTMigrateActions & FrontendOptions::ObjCMT_DesignatedInitializer) && 1937651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines canModify(ImplD)) 1938651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines inferDesignatedInitializers(Ctx, ImplD); 1939651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1940d412999a3da6387dbfaf00f7647132082e94310eFariborz Jahanian } 1941b8941a15b6b5477a81c189614d0129070ac099f1Fariborz Jahanian if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) 1942b8941a15b6b5477a81c189614d0129070ac099f1Fariborz Jahanian AnnotateImplicitBridging(Ctx); 1943dead50d347e9517d80f007a93df6295f66aa0f00Fariborz Jahanian } 1944baf15574ebe70871b4682cdd5a87028bad1c9f6fFariborz Jahanian 1945651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (IsOutputFile) { 1946176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines std::error_code EC; 1947176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines llvm::raw_fd_ostream OS(MigrateDir, EC, llvm::sys::fs::F_None); 1948176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines if (EC) { 1949651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines DiagnosticsEngine &Diags = Ctx.getDiagnostics(); 1950651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Diags.Report(Diags.getCustomDiagID(DiagnosticsEngine::Error, "%0")) 1951176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines << EC.message(); 1952651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return; 1953651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1954651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1955651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines JSONEditWriter Writer(Ctx.getSourceManager(), OS); 1956651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Editor->applyRewrites(Writer); 1957651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return; 1958651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 1959651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 19604e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie Rewriter rewriter(Ctx.getSourceManager(), Ctx.getLangOpts()); 196130660a898545416f0fea2d717f16f75640001e38Ted Kremenek RewritesReceiver Rec(rewriter); 196230660a898545416f0fea2d717f16f75640001e38Ted Kremenek Editor->applyRewrites(Rec); 196330660a898545416f0fea2d717f16f75640001e38Ted Kremenek 196430660a898545416f0fea2d717f16f75640001e38Ted Kremenek for (Rewriter::buffer_iterator 196530660a898545416f0fea2d717f16f75640001e38Ted Kremenek I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) { 196630660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileID FID = I->first; 196730660a898545416f0fea2d717f16f75640001e38Ted Kremenek RewriteBuffer &buf = I->second; 196830660a898545416f0fea2d717f16f75640001e38Ted Kremenek const FileEntry *file = Ctx.getSourceManager().getFileEntryForID(FID); 196930660a898545416f0fea2d717f16f75640001e38Ted Kremenek assert(file); 1970cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko SmallString<512> newText; 197130660a898545416f0fea2d717f16f75640001e38Ted Kremenek llvm::raw_svector_ostream vecOS(newText); 197230660a898545416f0fea2d717f16f75640001e38Ted Kremenek buf.write(vecOS); 1973176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines std::unique_ptr<llvm::MemoryBuffer> memBuf( 1974176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines llvm::MemoryBuffer::getMemBufferCopy( 1975176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines StringRef(newText.data(), newText.size()), file->getName())); 1976cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko SmallString<64> filePath(file->getName()); 197730660a898545416f0fea2d717f16f75640001e38Ted Kremenek FileMgr.FixupRelativePath(filePath); 1978176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Remapper.remap(filePath.str(), std::move(memBuf)); 197930660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 198030660a898545416f0fea2d717f16f75640001e38Ted Kremenek 198130660a898545416f0fea2d717f16f75640001e38Ted Kremenek if (IsOutputFile) { 198230660a898545416f0fea2d717f16f75640001e38Ted Kremenek Remapper.flushToFile(MigrateDir, Ctx.getDiagnostics()); 198330660a898545416f0fea2d717f16f75640001e38Ted Kremenek } else { 198430660a898545416f0fea2d717f16f75640001e38Ted Kremenek Remapper.flushToDisk(MigrateDir, Ctx.getDiagnostics()); 198530660a898545416f0fea2d717f16f75640001e38Ted Kremenek } 198630660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 198730660a898545416f0fea2d717f16f75640001e38Ted Kremenek 198830660a898545416f0fea2d717f16f75640001e38Ted Kremenekbool MigrateSourceAction::BeginInvocation(CompilerInstance &CI) { 1989013a254a5b85cfb54066e4022649368689c9ab06Argyrios Kyrtzidis CI.getDiagnostics().setIgnoreAllWarnings(true); 199030660a898545416f0fea2d717f16f75640001e38Ted Kremenek return true; 199130660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 199230660a898545416f0fea2d717f16f75640001e38Ted Kremenek 19932c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidisstatic std::vector<std::string> getWhiteListFilenames(StringRef DirPath) { 19942c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis using namespace llvm::sys::fs; 19952c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis using namespace llvm::sys::path; 19962c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis 19972c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis std::vector<std::string> Filenames; 19982c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis if (DirPath.empty() || !is_directory(DirPath)) 19992c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis return Filenames; 2000c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines 2001c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines std::error_code EC; 20022c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis directory_iterator DI = directory_iterator(DirPath, EC); 20032c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis directory_iterator DE; 20042c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis for (; !EC && DI != DE; DI = DI.increment(EC)) { 20052c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis if (is_regular_file(DI->path())) 20062c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis Filenames.push_back(filename(DI->path())); 20072c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis } 20082c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis 20092c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis return Filenames; 20102c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis} 20112c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis 2012176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hinesstd::unique_ptr<ASTConsumer> 2013176edba5311f6eff0cad2631449885ddf4fbc9eaStephen HinesMigrateSourceAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { 201437ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis PPConditionalDirectiveRecord * 201537ed12720a35b7bfa1c4de73ad6f1c6c1c88ee17Argyrios Kyrtzidis PPRec = new PPConditionalDirectiveRecord(CI.getSourceManager()); 201602593f5c9769851b8fcf6f78736e8b63ce9692e3Argyrios Kyrtzidis unsigned ObjCMTAction = CI.getFrontendOpts().ObjCMTAction; 20179887f260a8d59d47ed31b5fc689909b464ffc18fArgyrios Kyrtzidis unsigned ObjCMTOpts = ObjCMTAction; 20189887f260a8d59d47ed31b5fc689909b464ffc18fArgyrios Kyrtzidis // These are companion flags, they do not enable transformations. 20199887f260a8d59d47ed31b5fc689909b464ffc18fArgyrios Kyrtzidis ObjCMTOpts &= ~(FrontendOptions::ObjCMT_AtomicProperty | 20209887f260a8d59d47ed31b5fc689909b464ffc18fArgyrios Kyrtzidis FrontendOptions::ObjCMT_NsAtomicIOSOnlyProperty); 20219887f260a8d59d47ed31b5fc689909b464ffc18fArgyrios Kyrtzidis if (ObjCMTOpts == FrontendOptions::ObjCMT_None) { 202202593f5c9769851b8fcf6f78736e8b63ce9692e3Argyrios Kyrtzidis // If no specific option was given, enable literals+subscripting transforms 202302593f5c9769851b8fcf6f78736e8b63ce9692e3Argyrios Kyrtzidis // by default. 20249887f260a8d59d47ed31b5fc689909b464ffc18fArgyrios Kyrtzidis ObjCMTAction |= FrontendOptions::ObjCMT_Literals | 20259887f260a8d59d47ed31b5fc689909b464ffc18fArgyrios Kyrtzidis FrontendOptions::ObjCMT_Subscripting; 202602593f5c9769851b8fcf6f78736e8b63ce9692e3Argyrios Kyrtzidis } 2027176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines CI.getPreprocessor().addPPCallbacks(std::unique_ptr<PPCallbacks>(PPRec)); 20282c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis std::vector<std::string> WhiteList = 20292c050f6a68c4f871d26be63f8d598f1b64a8e16fArgyrios Kyrtzidis getWhiteListFilenames(CI.getFrontendOpts().ObjCMTWhiteListPath); 2030176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines return llvm::make_unique<ObjCMigrateASTConsumer>( 2031176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines CI.getFrontendOpts().OutputFile, ObjCMTAction, Remapper, 2032176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines CI.getFileManager(), PPRec, CI.getPreprocessor(), 2033176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines /*isOutputFile=*/true, WhiteList); 203430660a898545416f0fea2d717f16f75640001e38Ted Kremenek} 2035651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2036651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesnamespace { 2037651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstruct EditEntry { 2038651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const FileEntry *File; 2039651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines unsigned Offset; 2040651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines unsigned RemoveLen; 2041651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string Text; 2042651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2043651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines EditEntry() : File(), Offset(), RemoveLen() {} 2044651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}; 2045651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 2046651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2047651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesnamespace llvm { 2048651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinestemplate<> struct DenseMapInfo<EditEntry> { 2049651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines static inline EditEntry getEmptyKey() { 2050651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines EditEntry Entry; 2051651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Entry.Offset = unsigned(-1); 2052651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return Entry; 2053651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2054651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines static inline EditEntry getTombstoneKey() { 2055651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines EditEntry Entry; 2056651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Entry.Offset = unsigned(-2); 2057651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return Entry; 2058651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2059651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines static unsigned getHashValue(const EditEntry& Val) { 2060651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines llvm::FoldingSetNodeID ID; 2061651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ID.AddPointer(Val.File); 2062651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ID.AddInteger(Val.Offset); 2063651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ID.AddInteger(Val.RemoveLen); 2064651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ID.AddString(Val.Text); 2065651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return ID.ComputeHash(); 2066651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2067651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines static bool isEqual(const EditEntry &LHS, const EditEntry &RHS) { 2068651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return LHS.File == RHS.File && 2069651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines LHS.Offset == RHS.Offset && 2070651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines LHS.RemoveLen == RHS.RemoveLen && 2071651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines LHS.Text == RHS.Text; 2072651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2073651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}; 2074651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 2075651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2076651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesnamespace { 2077651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesclass RemapFileParser { 2078651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FileManager &FileMgr; 2079651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2080651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinespublic: 2081651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines RemapFileParser(FileManager &FileMgr) : FileMgr(FileMgr) { } 2082651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2083651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool parse(StringRef File, SmallVectorImpl<EditEntry> &Entries) { 2084651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines using namespace llvm::yaml; 2085651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2086c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr = 2087c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines llvm::MemoryBuffer::getFile(File); 2088c568f1e98938584c0ef0b12ae5018ff7d90a4072Stephen Hines if (!FileBufOrErr) 2089651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return true; 2090651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2091651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines llvm::SourceMgr SM; 2092176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Stream YAMLStream(FileBufOrErr.get()->getMemBufferRef(), SM); 2093651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines document_iterator I = YAMLStream.begin(); 2094651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (I == YAMLStream.end()) 2095651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return true; 2096651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Node *Root = I->getRoot(); 2097651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!Root) 2098651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return true; 2099651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2100651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SequenceNode *SeqNode = dyn_cast<SequenceNode>(Root); 2101651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!SeqNode) 2102651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return true; 2103651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2104651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (SequenceNode::iterator 2105651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines AI = SeqNode->begin(), AE = SeqNode->end(); AI != AE; ++AI) { 2106651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines MappingNode *MapNode = dyn_cast<MappingNode>(&*AI); 2107651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!MapNode) 2108651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 2109651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines parseEdit(MapNode, Entries); 2110651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2111651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2112651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return false; 2113651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2114651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2115651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesprivate: 2116651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void parseEdit(llvm::yaml::MappingNode *Node, 2117651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SmallVectorImpl<EditEntry> &Entries) { 2118651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines using namespace llvm::yaml; 2119651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines EditEntry Entry; 2120651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool Ignore = false; 2121651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2122651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (MappingNode::iterator 2123651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines KVI = Node->begin(), KVE = Node->end(); KVI != KVE; ++KVI) { 2124651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ScalarNode *KeyString = dyn_cast<ScalarNode>((*KVI).getKey()); 2125651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!KeyString) 2126651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 2127651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SmallString<10> KeyStorage; 2128651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines StringRef Key = KeyString->getValue(KeyStorage); 2129651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2130651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ScalarNode *ValueString = dyn_cast<ScalarNode>((*KVI).getValue()); 2131651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!ValueString) 2132651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 2133651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SmallString<64> ValueStorage; 2134651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines StringRef Val = ValueString->getValue(ValueStorage); 2135651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2136651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Key == "file") { 2137651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const FileEntry *FE = FileMgr.getFile(Val); 2138651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!FE) 2139651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Ignore = true; 2140651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Entry.File = FE; 2141651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } else if (Key == "offset") { 2142651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Val.getAsInteger(10, Entry.Offset)) 2143651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Ignore = true; 2144651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } else if (Key == "remove") { 2145651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Val.getAsInteger(10, Entry.RemoveLen)) 2146651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Ignore = true; 2147651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } else if (Key == "text") { 2148651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Entry.Text = Val; 2149651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2150651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2151651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2152651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!Ignore) 2153651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Entries.push_back(Entry); 2154651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2155651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}; 2156651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 2157651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2158651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic bool reportDiag(const Twine &Err, DiagnosticsEngine &Diag) { 2159651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Diag.Report(Diag.getCustomDiagID(DiagnosticsEngine::Error, "%0")) 2160651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines << Err.str(); 2161651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return true; 2162651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 2163651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2164651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic std::string applyEditsToTemp(const FileEntry *FE, 2165651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ArrayRef<EditEntry> Edits, 2166651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FileManager &FileMgr, 2167651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines DiagnosticsEngine &Diag) { 2168651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines using namespace llvm::sys; 2169651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2170651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SourceManager SM(Diag, FileMgr); 2171651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FileID FID = SM.createFileID(FE, SourceLocation(), SrcMgr::C_User); 2172651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines LangOptions LangOpts; 2173651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines edit::EditedSource Editor(SM, LangOpts); 2174651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (ArrayRef<EditEntry>::iterator 2175651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines I = Edits.begin(), E = Edits.end(); I != E; ++I) { 2176651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const EditEntry &Entry = *I; 2177651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines assert(Entry.File == FE); 2178651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SourceLocation Loc = 2179651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SM.getLocForStartOfFile(FID).getLocWithOffset(Entry.Offset); 2180651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CharSourceRange Range; 2181651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Entry.RemoveLen != 0) { 2182651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Range = CharSourceRange::getCharRange(Loc, 2183651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Loc.getLocWithOffset(Entry.RemoveLen)); 2184651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2185651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2186651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines edit::Commit commit(Editor); 2187651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Range.isInvalid()) { 2188651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines commit.insert(Loc, Entry.Text); 2189651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } else if (Entry.Text.empty()) { 2190651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines commit.remove(Range); 2191651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } else { 2192651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines commit.replace(Range, Entry.Text); 2193651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2194651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Editor.commit(commit); 2195651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2196651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2197651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Rewriter rewriter(SM, LangOpts); 2198651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines RewritesReceiver Rec(rewriter); 2199651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Editor.applyRewrites(Rec); 2200651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2201651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const RewriteBuffer *Buf = rewriter.getRewriteBufferFor(FID); 2202651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SmallString<512> NewText; 2203651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines llvm::raw_svector_ostream OS(NewText); 2204651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Buf->write(OS); 2205651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2206651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SmallString<64> TempPath; 2207651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines int FD; 2208651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (fs::createTemporaryFile(path::filename(FE->getName()), 2209a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar path::extension(FE->getName()).drop_front(), FD, 2210651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines TempPath)) { 2211651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines reportDiag("Could not create file: " + TempPath.str(), Diag); 2212651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return std::string(); 2213651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2214651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2215651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines llvm::raw_fd_ostream TmpOut(FD, /*shouldClose=*/true); 2216651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines TmpOut.write(NewText.data(), NewText.size()); 2217651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines TmpOut.close(); 2218651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2219651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return TempPath.str(); 2220651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 2221651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2222651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesbool arcmt::getFileRemappingsFromFileList( 2223651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::vector<std::pair<std::string,std::string> > &remap, 2224651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ArrayRef<StringRef> remapFiles, 2225651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines DiagnosticConsumer *DiagClient) { 2226651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool hasErrorOccurred = false; 2227651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2228651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FileSystemOptions FSOpts; 2229651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FileManager FileMgr(FSOpts); 2230651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines RemapFileParser Parser(FileMgr); 2231651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2232651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 2233651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines IntrusiveRefCntPtr<DiagnosticsEngine> Diags( 2234651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines new DiagnosticsEngine(DiagID, new DiagnosticOptions, 2235651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines DiagClient, /*ShouldOwnClient=*/false)); 2236651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2237651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines typedef llvm::DenseMap<const FileEntry *, std::vector<EditEntry> > 2238651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FileEditEntriesTy; 2239651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FileEditEntriesTy FileEditEntries; 2240651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2241651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines llvm::DenseSet<EditEntry> EntriesSet; 2242651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2243651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (ArrayRef<StringRef>::iterator 2244651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines I = remapFiles.begin(), E = remapFiles.end(); I != E; ++I) { 2245651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SmallVector<EditEntry, 16> Entries; 2246651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (Parser.parse(*I, Entries)) 2247651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 2248651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2249651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (SmallVectorImpl<EditEntry>::iterator 2250651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines EI = Entries.begin(), EE = Entries.end(); EI != EE; ++EI) { 2251651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines EditEntry &Entry = *EI; 2252651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!Entry.File) 2253651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 2254651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::pair<llvm::DenseSet<EditEntry>::iterator, bool> 2255651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Insert = EntriesSet.insert(Entry); 2256651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (!Insert.second) 2257651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 2258651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2259651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FileEditEntries[Entry.File].push_back(Entry); 2260651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2261651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2262651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2263651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (FileEditEntriesTy::iterator 2264651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines I = FileEditEntries.begin(), E = FileEditEntries.end(); I != E; ++I) { 2265651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines std::string TempFile = applyEditsToTemp(I->first, I->second, 2266651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines FileMgr, *Diags); 2267651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (TempFile.empty()) { 2268651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines hasErrorOccurred = true; 2269651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines continue; 2270651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2271651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2272b6d6993e6e6d3daf4d9876794254d20a134e37c2Pirama Arumuga Nainar remap.emplace_back(I->first->getName(), TempFile); 2273651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 2274651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 2275651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return hasErrorOccurred; 2276651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 2277