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