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