clang API Documentation

ObjCMT.cpp
Go to the documentation of this file.
00001 //===--- ObjCMT.cpp - ObjC Migrate Tool -----------------------------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 
00010 #include "Transforms.h"
00011 #include "clang/ARCMigrate/ARCMT.h"
00012 #include "clang/ARCMigrate/ARCMTActions.h"
00013 #include "clang/AST/ASTConsumer.h"
00014 #include "clang/AST/ASTContext.h"
00015 #include "clang/AST/Attr.h"
00016 #include "clang/AST/NSAPI.h"
00017 #include "clang/AST/ParentMap.h"
00018 #include "clang/AST/RecursiveASTVisitor.h"
00019 #include "clang/Analysis/DomainSpecific/CocoaConventions.h"
00020 #include "clang/Basic/FileManager.h"
00021 #include "clang/Edit/Commit.h"
00022 #include "clang/Edit/EditedSource.h"
00023 #include "clang/Edit/EditsReceiver.h"
00024 #include "clang/Edit/Rewriters.h"
00025 #include "clang/Frontend/CompilerInstance.h"
00026 #include "clang/Frontend/MultiplexConsumer.h"
00027 #include "clang/Lex/PPConditionalDirectiveRecord.h"
00028 #include "clang/Lex/Preprocessor.h"
00029 #include "clang/Rewrite/Core/Rewriter.h"
00030 #include "clang/StaticAnalyzer/Checkers/ObjCRetainCount.h"
00031 #include "llvm/ADT/SmallString.h"
00032 #include "llvm/Support/Path.h"
00033 #include "llvm/Support/SourceMgr.h"
00034 #include "llvm/Support/YAMLParser.h"
00035 
00036 using namespace clang;
00037 using namespace arcmt;
00038 using namespace ento::objc_retain;
00039 
00040 namespace {
00041 
00042 class ObjCMigrateASTConsumer : public ASTConsumer {
00043   enum CF_BRIDGING_KIND {
00044     CF_BRIDGING_NONE,
00045     CF_BRIDGING_ENABLE,
00046     CF_BRIDGING_MAY_INCLUDE
00047   };
00048   
00049   void migrateDecl(Decl *D);
00050   void migrateObjCInterfaceDecl(ASTContext &Ctx, ObjCContainerDecl *D);
00051   void migrateProtocolConformance(ASTContext &Ctx,
00052                                   const ObjCImplementationDecl *ImpDecl);
00053   void CacheObjCNSIntegerTypedefed(const TypedefDecl *TypedefDcl);
00054   bool migrateNSEnumDecl(ASTContext &Ctx, const EnumDecl *EnumDcl,
00055                      const TypedefDecl *TypedefDcl);
00056   void migrateAllMethodInstaceType(ASTContext &Ctx, ObjCContainerDecl *CDecl);
00057   void migrateMethodInstanceType(ASTContext &Ctx, ObjCContainerDecl *CDecl,
00058                                  ObjCMethodDecl *OM);
00059   bool migrateProperty(ASTContext &Ctx, ObjCContainerDecl *D, ObjCMethodDecl *OM);
00060   void migrateNsReturnsInnerPointer(ASTContext &Ctx, ObjCMethodDecl *OM);
00061   void migratePropertyNsReturnsInnerPointer(ASTContext &Ctx, ObjCPropertyDecl *P);
00062   void migrateFactoryMethod(ASTContext &Ctx, ObjCContainerDecl *CDecl,
00063                             ObjCMethodDecl *OM,
00064                             ObjCInstanceTypeFamily OIT_Family = OIT_None);
00065   
00066   void migrateCFAnnotation(ASTContext &Ctx, const Decl *Decl);
00067   void AddCFAnnotations(ASTContext &Ctx, const CallEffects &CE,
00068                         const FunctionDecl *FuncDecl, bool ResultAnnotated);
00069   void AddCFAnnotations(ASTContext &Ctx, const CallEffects &CE,
00070                         const ObjCMethodDecl *MethodDecl, bool ResultAnnotated);
00071   
00072   void AnnotateImplicitBridging(ASTContext &Ctx);
00073   
00074   CF_BRIDGING_KIND migrateAddFunctionAnnotation(ASTContext &Ctx,
00075                                                 const FunctionDecl *FuncDecl);
00076   
00077   void migrateARCSafeAnnotation(ASTContext &Ctx, ObjCContainerDecl *CDecl);
00078   
00079   void migrateAddMethodAnnotation(ASTContext &Ctx,
00080                                   const ObjCMethodDecl *MethodDecl);
00081 
00082   void inferDesignatedInitializers(ASTContext &Ctx,
00083                                    const ObjCImplementationDecl *ImplD);
00084   
00085   bool InsertFoundation(ASTContext &Ctx, SourceLocation Loc);
00086 
00087 public:
00088   std::string MigrateDir;
00089   unsigned ASTMigrateActions;
00090   FileID FileId;
00091   const TypedefDecl *NSIntegerTypedefed;
00092   const TypedefDecl *NSUIntegerTypedefed;
00093   std::unique_ptr<NSAPI> NSAPIObj;
00094   std::unique_ptr<edit::EditedSource> Editor;
00095   FileRemapper &Remapper;
00096   FileManager &FileMgr;
00097   const PPConditionalDirectiveRecord *PPRec;
00098   Preprocessor &PP;
00099   bool IsOutputFile;
00100   bool FoundationIncluded;
00101   llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ObjCProtocolDecls;
00102   llvm::SmallVector<const Decl *, 8> CFFunctionIBCandidates;
00103   llvm::StringMap<char> WhiteListFilenames;
00104   
00105   ObjCMigrateASTConsumer(StringRef migrateDir,
00106                          unsigned astMigrateActions,
00107                          FileRemapper &remapper,
00108                          FileManager &fileMgr,
00109                          const PPConditionalDirectiveRecord *PPRec,
00110                          Preprocessor &PP,
00111                          bool isOutputFile,
00112                          ArrayRef<std::string> WhiteList)
00113   : MigrateDir(migrateDir),
00114     ASTMigrateActions(astMigrateActions),
00115     NSIntegerTypedefed(nullptr), NSUIntegerTypedefed(nullptr),
00116     Remapper(remapper), FileMgr(fileMgr), PPRec(PPRec), PP(PP),
00117     IsOutputFile(isOutputFile),
00118     FoundationIncluded(false){
00119 
00120     for (ArrayRef<std::string>::iterator
00121            I = WhiteList.begin(), E = WhiteList.end(); I != E; ++I) {
00122       WhiteListFilenames.GetOrCreateValue(*I);
00123     }
00124   }
00125 
00126 protected:
00127   void Initialize(ASTContext &Context) override {
00128     NSAPIObj.reset(new NSAPI(Context));
00129     Editor.reset(new edit::EditedSource(Context.getSourceManager(),
00130                                         Context.getLangOpts(),
00131                                         PPRec));
00132   }
00133 
00134   bool HandleTopLevelDecl(DeclGroupRef DG) override {
00135     for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
00136       migrateDecl(*I);
00137     return true;
00138   }
00139   void HandleInterestingDecl(DeclGroupRef DG) override {
00140     // Ignore decls from the PCH.
00141   }
00142   void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) override {
00143     ObjCMigrateASTConsumer::HandleTopLevelDecl(DG);
00144   }
00145 
00146   void HandleTranslationUnit(ASTContext &Ctx) override;
00147 
00148   bool canModifyFile(StringRef Path) {
00149     if (WhiteListFilenames.empty())
00150       return true;
00151     return WhiteListFilenames.find(llvm::sys::path::filename(Path))
00152         != WhiteListFilenames.end();
00153   }
00154   bool canModifyFile(const FileEntry *FE) {
00155     if (!FE)
00156       return false;
00157     return canModifyFile(FE->getName());
00158   }
00159   bool canModifyFile(FileID FID) {
00160     if (FID.isInvalid())
00161       return false;
00162     return canModifyFile(PP.getSourceManager().getFileEntryForID(FID));
00163   }
00164 
00165   bool canModify(const Decl *D) {
00166     if (!D)
00167       return false;
00168     if (const ObjCCategoryImplDecl *CatImpl = dyn_cast<ObjCCategoryImplDecl>(D))
00169       return canModify(CatImpl->getCategoryDecl());
00170     if (const ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D))
00171       return canModify(Impl->getClassInterface());
00172     if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
00173       return canModify(cast<Decl>(MD->getDeclContext()));
00174 
00175     FileID FID = PP.getSourceManager().getFileID(D->getLocation());
00176     return canModifyFile(FID);
00177   }
00178 };
00179 
00180 }
00181 
00182 ObjCMigrateAction::ObjCMigrateAction(FrontendAction *WrappedAction,
00183                                      StringRef migrateDir,
00184                                      unsigned migrateAction)
00185   : WrapperFrontendAction(WrappedAction), MigrateDir(migrateDir),
00186     ObjCMigAction(migrateAction),
00187     CompInst(nullptr) {
00188   if (MigrateDir.empty())
00189     MigrateDir = "."; // user current directory if none is given.
00190 }
00191 
00192 std::unique_ptr<ASTConsumer>
00193 ObjCMigrateAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
00194   PPConditionalDirectiveRecord *
00195     PPRec = new PPConditionalDirectiveRecord(CompInst->getSourceManager());
00196   CI.getPreprocessor().addPPCallbacks(std::unique_ptr<PPCallbacks>(PPRec));
00197   std::vector<std::unique_ptr<ASTConsumer>> Consumers;
00198   Consumers.push_back(WrapperFrontendAction::CreateASTConsumer(CI, InFile));
00199   Consumers.push_back(llvm::make_unique<ObjCMigrateASTConsumer>(
00200       MigrateDir, ObjCMigAction, Remapper, CompInst->getFileManager(), PPRec,
00201       CompInst->getPreprocessor(), false, None));
00202   return llvm::make_unique<MultiplexConsumer>(std::move(Consumers));
00203 }
00204 
00205 bool ObjCMigrateAction::BeginInvocation(CompilerInstance &CI) {
00206   Remapper.initFromDisk(MigrateDir, CI.getDiagnostics(),
00207                         /*ignoreIfFilesChanges=*/true);
00208   CompInst = &CI;
00209   CI.getDiagnostics().setIgnoreAllWarnings(true);
00210   return true;
00211 }
00212 
00213 namespace {
00214   // FIXME. This duplicates one in RewriteObjCFoundationAPI.cpp
00215   bool subscriptOperatorNeedsParens(const Expr *FullExpr) {
00216     const Expr* Expr = FullExpr->IgnoreImpCasts();
00217     if (isa<ArraySubscriptExpr>(Expr) ||
00218         isa<CallExpr>(Expr) ||
00219         isa<DeclRefExpr>(Expr) ||
00220         isa<CXXNamedCastExpr>(Expr) ||
00221         isa<CXXConstructExpr>(Expr) ||
00222         isa<CXXThisExpr>(Expr) ||
00223         isa<CXXTypeidExpr>(Expr) ||
00224         isa<CXXUnresolvedConstructExpr>(Expr) ||
00225         isa<ObjCMessageExpr>(Expr) ||
00226         isa<ObjCPropertyRefExpr>(Expr) ||
00227         isa<ObjCProtocolExpr>(Expr) ||
00228         isa<MemberExpr>(Expr) ||
00229         isa<ObjCIvarRefExpr>(Expr) ||
00230         isa<ParenExpr>(FullExpr) ||
00231         isa<ParenListExpr>(Expr) ||
00232         isa<SizeOfPackExpr>(Expr))
00233       return false;
00234     
00235     return true;
00236   }
00237   
00238   /// \brief - Rewrite message expression for Objective-C setter and getters into
00239   /// property-dot syntax.
00240   bool rewriteToPropertyDotSyntax(const ObjCMessageExpr *Msg,
00241                                   Preprocessor &PP,
00242                                   const NSAPI &NS, edit::Commit &commit,
00243                                   const ParentMap *PMap) {
00244     if (!Msg || Msg->isImplicit() ||
00245         Msg->getReceiverKind() != ObjCMessageExpr::Instance)
00246       return false;
00247     const ObjCMethodDecl *Method = Msg->getMethodDecl();
00248     if (!Method)
00249       return false;
00250     if (!Method->isPropertyAccessor())
00251       return false;
00252     
00253     const ObjCInterfaceDecl *IFace =
00254       NS.getASTContext().getObjContainingInterface(Method);
00255     if (!IFace)
00256       return false;
00257     
00258     const ObjCPropertyDecl *Prop = Method->findPropertyDecl();
00259     if (!Prop)
00260       return false;
00261     
00262     SourceRange MsgRange = Msg->getSourceRange();
00263     const Expr *receiver = Msg->getInstanceReceiver();
00264     bool NeedsParen = subscriptOperatorNeedsParens(receiver);
00265     bool IsGetter = (Msg->getNumArgs() == 0);
00266     if (IsGetter) {
00267       // Find space location range between receiver expression and getter method.
00268       SourceLocation BegLoc = receiver->getLocEnd();
00269       BegLoc = PP.getLocForEndOfToken(BegLoc);
00270       SourceLocation EndLoc = Msg->getSelectorLoc(0);
00271       SourceRange SpaceRange(BegLoc, EndLoc);
00272       std::string PropertyDotString;
00273       // rewrite getter method expression into: receiver.property or
00274       // (receiver).property
00275       if (NeedsParen) {
00276         commit.insertBefore(receiver->getLocStart(), "(");
00277         PropertyDotString = ").";
00278       }
00279       else
00280         PropertyDotString = ".";
00281       PropertyDotString += Prop->getName();
00282       commit.replace(SpaceRange, PropertyDotString);
00283       
00284       // remove '[' ']'
00285       commit.replace(SourceRange(MsgRange.getBegin(), MsgRange.getBegin()), "");
00286       commit.replace(SourceRange(MsgRange.getEnd(), MsgRange.getEnd()), "");
00287     } else {
00288       SourceRange ReceiverRange = receiver->getSourceRange();
00289       if (NeedsParen)
00290         commit.insertWrap("(", ReceiverRange, ")");
00291       std::string PropertyDotString = ".";
00292       PropertyDotString += Prop->getName();
00293       PropertyDotString += " =";
00294       const Expr*const* Args = Msg->getArgs();
00295       const Expr *RHS = Args[0];
00296       if (!RHS)
00297         return false;
00298       SourceLocation BegLoc = ReceiverRange.getEnd();
00299       BegLoc = PP.getLocForEndOfToken(BegLoc);
00300       SourceLocation EndLoc = RHS->getLocStart();
00301       EndLoc = EndLoc.getLocWithOffset(-1);
00302       SourceRange Range(BegLoc, EndLoc);
00303       commit.replace(Range, PropertyDotString);
00304       // remove '[' ']'
00305       commit.replace(SourceRange(MsgRange.getBegin(), MsgRange.getBegin()), "");
00306       commit.replace(SourceRange(MsgRange.getEnd(), MsgRange.getEnd()), "");
00307     }
00308     return true;
00309   }
00310   
00311 
00312 class ObjCMigrator : public RecursiveASTVisitor<ObjCMigrator> {
00313   ObjCMigrateASTConsumer &Consumer;
00314   ParentMap &PMap;
00315 
00316 public:
00317   ObjCMigrator(ObjCMigrateASTConsumer &consumer, ParentMap &PMap)
00318     : Consumer(consumer), PMap(PMap) { }
00319 
00320   bool shouldVisitTemplateInstantiations() const { return false; }
00321   bool shouldWalkTypesOfTypeLocs() const { return false; }
00322 
00323   bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
00324     if (Consumer.ASTMigrateActions & FrontendOptions::ObjCMT_Literals) {
00325       edit::Commit commit(*Consumer.Editor);
00326       edit::rewriteToObjCLiteralSyntax(E, *Consumer.NSAPIObj, commit, &PMap);
00327       Consumer.Editor->commit(commit);
00328     }
00329 
00330     if (Consumer.ASTMigrateActions & FrontendOptions::ObjCMT_Subscripting) {
00331       edit::Commit commit(*Consumer.Editor);
00332       edit::rewriteToObjCSubscriptSyntax(E, *Consumer.NSAPIObj, commit);
00333       Consumer.Editor->commit(commit);
00334     }
00335 
00336     if (Consumer.ASTMigrateActions & FrontendOptions::ObjCMT_PropertyDotSyntax) {
00337       edit::Commit commit(*Consumer.Editor);
00338       rewriteToPropertyDotSyntax(E, Consumer.PP, *Consumer.NSAPIObj,
00339                                  commit, &PMap);
00340       Consumer.Editor->commit(commit);
00341     }
00342 
00343     return true;
00344   }
00345 
00346   bool TraverseObjCMessageExpr(ObjCMessageExpr *E) {
00347     // Do depth first; we want to rewrite the subexpressions first so that if
00348     // we have to move expressions we will move them already rewritten.
00349     for (Stmt::child_range range = E->children(); range; ++range)
00350       if (!TraverseStmt(*range))
00351         return false;
00352 
00353     return WalkUpFromObjCMessageExpr(E);
00354   }
00355 };
00356 
00357 class BodyMigrator : public RecursiveASTVisitor<BodyMigrator> {
00358   ObjCMigrateASTConsumer &Consumer;
00359   std::unique_ptr<ParentMap> PMap;
00360 
00361 public:
00362   BodyMigrator(ObjCMigrateASTConsumer &consumer) : Consumer(consumer) { }
00363 
00364   bool shouldVisitTemplateInstantiations() const { return false; }
00365   bool shouldWalkTypesOfTypeLocs() const { return false; }
00366 
00367   bool TraverseStmt(Stmt *S) {
00368     PMap.reset(new ParentMap(S));
00369     ObjCMigrator(Consumer, *PMap).TraverseStmt(S);
00370     return true;
00371   }
00372 };
00373 }
00374 
00375 void ObjCMigrateASTConsumer::migrateDecl(Decl *D) {
00376   if (!D)
00377     return;
00378   if (isa<ObjCMethodDecl>(D))
00379     return; // Wait for the ObjC container declaration.
00380 
00381   BodyMigrator(*this).TraverseDecl(D);
00382 }
00383 
00384 static void append_attr(std::string &PropertyString, const char *attr,
00385                         bool &LParenAdded) {
00386   if (!LParenAdded) {
00387     PropertyString += "(";
00388     LParenAdded = true;
00389   }
00390   else
00391     PropertyString += ", ";
00392   PropertyString += attr;
00393 }
00394 
00395 static
00396 void MigrateBlockOrFunctionPointerTypeVariable(std::string & PropertyString,
00397                                                const std::string& TypeString,
00398                                                const char *name) {
00399   const char *argPtr = TypeString.c_str();
00400   int paren = 0;
00401   while (*argPtr) {
00402     switch (*argPtr) {
00403       case '(':
00404         PropertyString += *argPtr;
00405         paren++;
00406         break;
00407       case ')':
00408         PropertyString += *argPtr;
00409         paren--;
00410         break;
00411       case '^':
00412       case '*':
00413         PropertyString += (*argPtr);
00414         if (paren == 1) {
00415           PropertyString += name;
00416           name = "";
00417         }
00418         break;
00419       default:
00420         PropertyString += *argPtr;
00421         break;
00422     }
00423     argPtr++;
00424   }
00425 }
00426 
00427 static const char *PropertyMemoryAttribute(ASTContext &Context, QualType ArgType) {
00428   Qualifiers::ObjCLifetime propertyLifetime = ArgType.getObjCLifetime();
00429   bool RetainableObject = ArgType->isObjCRetainableType();
00430   if (RetainableObject &&
00431       (propertyLifetime == Qualifiers::OCL_Strong
00432        || propertyLifetime == Qualifiers::OCL_None)) {
00433     if (const ObjCObjectPointerType *ObjPtrTy =
00434         ArgType->getAs<ObjCObjectPointerType>()) {
00435       ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface();
00436       if (IDecl &&
00437           IDecl->lookupNestedProtocol(&Context.Idents.get("NSCopying")))
00438         return "copy";
00439       else
00440         return "strong";
00441     }
00442     else if (ArgType->isBlockPointerType())
00443       return "copy";
00444   } else if (propertyLifetime == Qualifiers::OCL_Weak)
00445     // TODO. More precise determination of 'weak' attribute requires
00446     // looking into setter's implementation for backing weak ivar.
00447     return "weak";
00448   else if (RetainableObject)
00449     return ArgType->isBlockPointerType() ? "copy" : "strong";
00450   return nullptr;
00451 }
00452 
00453 static void rewriteToObjCProperty(const ObjCMethodDecl *Getter,
00454                                   const ObjCMethodDecl *Setter,
00455                                   const NSAPI &NS, edit::Commit &commit,
00456                                   unsigned LengthOfPrefix,
00457                                   bool Atomic, bool UseNsIosOnlyMacro,
00458                                   bool AvailabilityArgsMatch) {
00459   ASTContext &Context = NS.getASTContext();
00460   bool LParenAdded = false;
00461   std::string PropertyString = "@property ";
00462   if (UseNsIosOnlyMacro && Context.Idents.get("NS_NONATOMIC_IOSONLY").hasMacroDefinition()) {
00463     PropertyString += "(NS_NONATOMIC_IOSONLY";
00464     LParenAdded = true;
00465   } else if (!Atomic) {
00466     PropertyString += "(nonatomic";
00467     LParenAdded = true;
00468   }
00469   
00470   std::string PropertyNameString = Getter->getNameAsString();
00471   StringRef PropertyName(PropertyNameString);
00472   if (LengthOfPrefix > 0) {
00473     if (!LParenAdded) {
00474       PropertyString += "(getter=";
00475       LParenAdded = true;
00476     }
00477     else
00478       PropertyString += ", getter=";
00479     PropertyString += PropertyNameString;
00480   }
00481   // Property with no setter may be suggested as a 'readonly' property.
00482   if (!Setter)
00483     append_attr(PropertyString, "readonly", LParenAdded);
00484   
00485   
00486   // Short circuit 'delegate' properties that contain the name "delegate" or
00487   // "dataSource", or have exact name "target" to have 'assign' attribute.
00488   if (PropertyName.equals("target") ||
00489       (PropertyName.find("delegate") != StringRef::npos) ||
00490       (PropertyName.find("dataSource") != StringRef::npos)) {
00491     QualType QT = Getter->getReturnType();
00492     if (!QT->isRealType())
00493       append_attr(PropertyString, "assign", LParenAdded);
00494   } else if (!Setter) {
00495     QualType ResType = Context.getCanonicalType(Getter->getReturnType());
00496     if (const char *MemoryManagementAttr = PropertyMemoryAttribute(Context, ResType))
00497       append_attr(PropertyString, MemoryManagementAttr, LParenAdded);
00498   } else {
00499     const ParmVarDecl *argDecl = *Setter->param_begin();
00500     QualType ArgType = Context.getCanonicalType(argDecl->getType());
00501     if (const char *MemoryManagementAttr = PropertyMemoryAttribute(Context, ArgType))
00502       append_attr(PropertyString, MemoryManagementAttr, LParenAdded);
00503   }
00504   if (LParenAdded)
00505     PropertyString += ')';
00506   QualType RT = Getter->getReturnType();
00507   if (!isa<TypedefType>(RT)) {
00508     // strip off any ARC lifetime qualifier.
00509     QualType CanResultTy = Context.getCanonicalType(RT);
00510     if (CanResultTy.getQualifiers().hasObjCLifetime()) {
00511       Qualifiers Qs = CanResultTy.getQualifiers();
00512       Qs.removeObjCLifetime();
00513       RT = Context.getQualifiedType(CanResultTy.getUnqualifiedType(), Qs);
00514     }
00515   }
00516   PropertyString += " ";
00517   PrintingPolicy SubPolicy(Context.getPrintingPolicy());
00518   SubPolicy.SuppressStrongLifetime = true;
00519   SubPolicy.SuppressLifetimeQualifiers = true;
00520   std::string TypeString = RT.getAsString(SubPolicy);
00521   if (LengthOfPrefix > 0) {
00522     // property name must strip off "is" and lower case the first character
00523     // after that; e.g. isContinuous will become continuous.
00524     StringRef PropertyNameStringRef(PropertyNameString);
00525     PropertyNameStringRef = PropertyNameStringRef.drop_front(LengthOfPrefix);
00526     PropertyNameString = PropertyNameStringRef;
00527     bool NoLowering = (isUppercase(PropertyNameString[0]) &&
00528                        PropertyNameString.size() > 1 &&
00529                        isUppercase(PropertyNameString[1]));
00530     if (!NoLowering)
00531       PropertyNameString[0] = toLowercase(PropertyNameString[0]);
00532   }
00533   if (RT->isBlockPointerType() || RT->isFunctionPointerType())
00534     MigrateBlockOrFunctionPointerTypeVariable(PropertyString,
00535                                               TypeString,
00536                                               PropertyNameString.c_str());
00537   else {
00538     char LastChar = TypeString[TypeString.size()-1];
00539     PropertyString += TypeString;
00540     if (LastChar != '*')
00541       PropertyString += ' ';
00542     PropertyString += PropertyNameString;
00543   }
00544   SourceLocation StartGetterSelectorLoc = Getter->getSelectorStartLoc();
00545   Selector GetterSelector = Getter->getSelector();
00546   
00547   SourceLocation EndGetterSelectorLoc =
00548     StartGetterSelectorLoc.getLocWithOffset(GetterSelector.getNameForSlot(0).size());
00549   commit.replace(CharSourceRange::getCharRange(Getter->getLocStart(),
00550                                                EndGetterSelectorLoc),
00551                  PropertyString);
00552   if (Setter && AvailabilityArgsMatch) {
00553     SourceLocation EndLoc = Setter->getDeclaratorEndLoc();
00554     // Get location past ';'
00555     EndLoc = EndLoc.getLocWithOffset(1);
00556     SourceLocation BeginOfSetterDclLoc = Setter->getLocStart();
00557     // FIXME. This assumes that setter decl; is immediately preceded by eoln.
00558     // It is trying to remove the setter method decl. line entirely.
00559     BeginOfSetterDclLoc = BeginOfSetterDclLoc.getLocWithOffset(-1);
00560     commit.remove(SourceRange(BeginOfSetterDclLoc, EndLoc));
00561   }
00562 }
00563 
00564 static bool IsCategoryNameWithDeprecatedSuffix(ObjCContainerDecl *D) {
00565   if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(D)) {
00566     StringRef Name = CatDecl->getName();
00567     return Name.endswith("Deprecated");
00568   }
00569   return false;
00570 }
00571 
00572 void ObjCMigrateASTConsumer::migrateObjCInterfaceDecl(ASTContext &Ctx,
00573                                                       ObjCContainerDecl *D) {
00574   if (D->isDeprecated() || IsCategoryNameWithDeprecatedSuffix(D))
00575     return;
00576     
00577   for (auto *Method : D->methods()) {
00578     if (Method->isDeprecated())
00579       continue;
00580     bool PropertyInferred = migrateProperty(Ctx, D, Method);
00581     // If a property is inferred, do not attempt to attach NS_RETURNS_INNER_POINTER to
00582     // the getter method as it ends up on the property itself which we don't want
00583     // to do unless -objcmt-returns-innerpointer-property  option is on.
00584     if (!PropertyInferred ||
00585         (ASTMigrateActions & FrontendOptions::ObjCMT_ReturnsInnerPointerProperty))
00586       if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation)
00587         migrateNsReturnsInnerPointer(Ctx, Method);
00588   }
00589   if (!(ASTMigrateActions & FrontendOptions::ObjCMT_ReturnsInnerPointerProperty))
00590     return;
00591   
00592   for (auto *Prop : D->properties()) {
00593     if ((ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) &&
00594         !Prop->isDeprecated())
00595       migratePropertyNsReturnsInnerPointer(Ctx, Prop);
00596   }
00597 }
00598 
00599 static bool
00600 ClassImplementsAllMethodsAndProperties(ASTContext &Ctx,
00601                                       const ObjCImplementationDecl *ImpDecl,
00602                                        const ObjCInterfaceDecl *IDecl,
00603                                       ObjCProtocolDecl *Protocol) {
00604   // In auto-synthesis, protocol properties are not synthesized. So,
00605   // a conforming protocol must have its required properties declared
00606   // in class interface.
00607   bool HasAtleastOneRequiredProperty = false;
00608   if (const ObjCProtocolDecl *PDecl = Protocol->getDefinition())
00609     for (const auto *Property : PDecl->properties()) {
00610       if (Property->getPropertyImplementation() == ObjCPropertyDecl::Optional)
00611         continue;
00612       HasAtleastOneRequiredProperty = true;
00613       DeclContext::lookup_const_result R = IDecl->lookup(Property->getDeclName());
00614       if (R.size() == 0) {
00615         // Relax the rule and look into class's implementation for a synthesize
00616         // or dynamic declaration. Class is implementing a property coming from
00617         // another protocol. This still makes the target protocol as conforming.
00618         if (!ImpDecl->FindPropertyImplDecl(
00619                                   Property->getDeclName().getAsIdentifierInfo()))
00620           return false;
00621       }
00622       else if (ObjCPropertyDecl *ClassProperty = dyn_cast<ObjCPropertyDecl>(R[0])) {
00623           if ((ClassProperty->getPropertyAttributes()
00624               != Property->getPropertyAttributes()) ||
00625               !Ctx.hasSameType(ClassProperty->getType(), Property->getType()))
00626             return false;
00627       }
00628       else
00629         return false;
00630     }
00631   
00632   // At this point, all required properties in this protocol conform to those
00633   // declared in the class.
00634   // Check that class implements the required methods of the protocol too.
00635   bool HasAtleastOneRequiredMethod = false;
00636   if (const ObjCProtocolDecl *PDecl = Protocol->getDefinition()) {
00637     if (PDecl->meth_begin() == PDecl->meth_end())
00638       return HasAtleastOneRequiredProperty;
00639     for (const auto *MD : PDecl->methods()) {
00640       if (MD->isImplicit())
00641         continue;
00642       if (MD->getImplementationControl() == ObjCMethodDecl::Optional)
00643         continue;
00644       DeclContext::lookup_const_result R = ImpDecl->lookup(MD->getDeclName());
00645       if (R.size() == 0)
00646         return false;
00647       bool match = false;
00648       HasAtleastOneRequiredMethod = true;
00649       for (unsigned I = 0, N = R.size(); I != N; ++I)
00650         if (ObjCMethodDecl *ImpMD = dyn_cast<ObjCMethodDecl>(R[0]))
00651           if (Ctx.ObjCMethodsAreEqual(MD, ImpMD)) {
00652             match = true;
00653             break;
00654           }
00655       if (!match)
00656         return false;
00657     }
00658   }
00659   if (HasAtleastOneRequiredProperty || HasAtleastOneRequiredMethod)
00660     return true;
00661   return false;
00662 }
00663 
00664 static bool rewriteToObjCInterfaceDecl(const ObjCInterfaceDecl *IDecl,
00665                     llvm::SmallVectorImpl<ObjCProtocolDecl*> &ConformingProtocols,
00666                     const NSAPI &NS, edit::Commit &commit) {
00667   const ObjCList<ObjCProtocolDecl> &Protocols = IDecl->getReferencedProtocols();
00668   std::string ClassString;
00669   SourceLocation EndLoc =
00670   IDecl->getSuperClass() ? IDecl->getSuperClassLoc() : IDecl->getLocation();
00671   
00672   if (Protocols.empty()) {
00673     ClassString = '<';
00674     for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
00675       ClassString += ConformingProtocols[i]->getNameAsString();
00676       if (i != (e-1))
00677         ClassString += ", ";
00678     }
00679     ClassString += "> ";
00680   }
00681   else {
00682     ClassString = ", ";
00683     for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
00684       ClassString += ConformingProtocols[i]->getNameAsString();
00685       if (i != (e-1))
00686         ClassString += ", ";
00687     }
00688     ObjCInterfaceDecl::protocol_loc_iterator PL = IDecl->protocol_loc_end() - 1;
00689     EndLoc = *PL;
00690   }
00691   
00692   commit.insertAfterToken(EndLoc, ClassString);
00693   return true;
00694 }
00695 
00696 static StringRef GetUnsignedName(StringRef NSIntegerName) {
00697   StringRef UnsignedName = llvm::StringSwitch<StringRef>(NSIntegerName)
00698     .Case("int8_t", "uint8_t")
00699     .Case("int16_t", "uint16_t")
00700     .Case("int32_t", "uint32_t")
00701     .Case("NSInteger", "NSUInteger")
00702     .Case("int64_t", "uint64_t")
00703     .Default(NSIntegerName);
00704   return UnsignedName;
00705 }
00706 
00707 static bool rewriteToNSEnumDecl(const EnumDecl *EnumDcl,
00708                                 const TypedefDecl *TypedefDcl,
00709                                 const NSAPI &NS, edit::Commit &commit,
00710                                 StringRef NSIntegerName,
00711                                 bool NSOptions) {
00712   std::string ClassString;
00713   if (NSOptions) {
00714     ClassString = "typedef NS_OPTIONS(";
00715     ClassString += GetUnsignedName(NSIntegerName);
00716   }
00717   else {
00718     ClassString = "typedef NS_ENUM(";
00719     ClassString += NSIntegerName;
00720   }
00721   ClassString += ", ";
00722   
00723   ClassString += TypedefDcl->getIdentifier()->getName();
00724   ClassString += ')';
00725   SourceRange R(EnumDcl->getLocStart(), EnumDcl->getLocStart());
00726   commit.replace(R, ClassString);
00727   SourceLocation EndOfEnumDclLoc = EnumDcl->getLocEnd();
00728   EndOfEnumDclLoc = trans::findSemiAfterLocation(EndOfEnumDclLoc,
00729                                                  NS.getASTContext(), /*IsDecl*/true);
00730   if (!EndOfEnumDclLoc.isInvalid()) {
00731     SourceRange EnumDclRange(EnumDcl->getLocStart(), EndOfEnumDclLoc);
00732     commit.insertFromRange(TypedefDcl->getLocStart(), EnumDclRange);
00733   }
00734   else
00735     return false;
00736   
00737   SourceLocation EndTypedefDclLoc = TypedefDcl->getLocEnd();
00738   EndTypedefDclLoc = trans::findSemiAfterLocation(EndTypedefDclLoc,
00739                                                  NS.getASTContext(), /*IsDecl*/true);
00740   if (!EndTypedefDclLoc.isInvalid()) {
00741     SourceRange TDRange(TypedefDcl->getLocStart(), EndTypedefDclLoc);
00742     commit.remove(TDRange);
00743   }
00744   else
00745     return false;
00746 
00747   EndOfEnumDclLoc = trans::findLocationAfterSemi(EnumDcl->getLocEnd(), NS.getASTContext(),
00748                                                  /*IsDecl*/true);
00749   if (!EndOfEnumDclLoc.isInvalid()) {
00750     SourceLocation BeginOfEnumDclLoc = EnumDcl->getLocStart();
00751     // FIXME. This assumes that enum decl; is immediately preceded by eoln.
00752     // It is trying to remove the enum decl. lines entirely.
00753     BeginOfEnumDclLoc = BeginOfEnumDclLoc.getLocWithOffset(-1);
00754     commit.remove(SourceRange(BeginOfEnumDclLoc, EndOfEnumDclLoc));
00755     return true;
00756   }
00757   return false;
00758 }
00759 
00760 static void rewriteToNSMacroDecl(const EnumDecl *EnumDcl,
00761                                 const TypedefDecl *TypedefDcl,
00762                                 const NSAPI &NS, edit::Commit &commit,
00763                                  bool IsNSIntegerType) {
00764   std::string ClassString =
00765     IsNSIntegerType ? "NS_ENUM(NSInteger, " : "NS_OPTIONS(NSUInteger, ";
00766   ClassString += TypedefDcl->getIdentifier()->getName();
00767   ClassString += ')';
00768   SourceRange R(EnumDcl->getLocStart(), EnumDcl->getLocStart());
00769   commit.replace(R, ClassString);
00770   // This is to remove spaces between '}' and typedef name.
00771   SourceLocation StartTypedefLoc = EnumDcl->getLocEnd();
00772   StartTypedefLoc = StartTypedefLoc.getLocWithOffset(+1);
00773   SourceLocation EndTypedefLoc = TypedefDcl->getLocEnd();
00774   
00775   commit.remove(SourceRange(StartTypedefLoc, EndTypedefLoc));
00776 }
00777 
00778 static bool UseNSOptionsMacro(Preprocessor &PP, ASTContext &Ctx,
00779                               const EnumDecl *EnumDcl) {
00780   bool PowerOfTwo = true;
00781   bool AllHexdecimalEnumerator = true;
00782   uint64_t MaxPowerOfTwoVal = 0;
00783   for (auto Enumerator : EnumDcl->enumerators()) {
00784     const Expr *InitExpr = Enumerator->getInitExpr();
00785     if (!InitExpr) {
00786       PowerOfTwo = false;
00787       AllHexdecimalEnumerator = false;
00788       continue;
00789     }
00790     InitExpr = InitExpr->IgnoreParenCasts();
00791     if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(InitExpr))
00792       if (BO->isShiftOp() || BO->isBitwiseOp())
00793         return true;
00794     
00795     uint64_t EnumVal = Enumerator->getInitVal().getZExtValue();
00796     if (PowerOfTwo && EnumVal) {
00797       if (!llvm::isPowerOf2_64(EnumVal))
00798         PowerOfTwo = false;
00799       else if (EnumVal > MaxPowerOfTwoVal)
00800         MaxPowerOfTwoVal = EnumVal;
00801     }
00802     if (AllHexdecimalEnumerator && EnumVal) {
00803       bool FoundHexdecimalEnumerator = false;
00804       SourceLocation EndLoc = Enumerator->getLocEnd();
00805       Token Tok;
00806       if (!PP.getRawToken(EndLoc, Tok, /*IgnoreWhiteSpace=*/true))
00807         if (Tok.isLiteral() && Tok.getLength() > 2) {
00808           if (const char *StringLit = Tok.getLiteralData())
00809             FoundHexdecimalEnumerator =
00810               (StringLit[0] == '0' && (toLowercase(StringLit[1]) == 'x'));
00811         }
00812       if (!FoundHexdecimalEnumerator)
00813         AllHexdecimalEnumerator = false;
00814     }
00815   }
00816   return AllHexdecimalEnumerator || (PowerOfTwo && (MaxPowerOfTwoVal > 2));
00817 }
00818 
00819 void ObjCMigrateASTConsumer::migrateProtocolConformance(ASTContext &Ctx,   
00820                                             const ObjCImplementationDecl *ImpDecl) {
00821   const ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface();
00822   if (!IDecl || ObjCProtocolDecls.empty() || IDecl->isDeprecated())
00823     return;
00824   // Find all implicit conforming protocols for this class
00825   // and make them explicit.
00826   llvm::SmallPtrSet<ObjCProtocolDecl *, 8> ExplicitProtocols;
00827   Ctx.CollectInheritedProtocols(IDecl, ExplicitProtocols);
00828   llvm::SmallVector<ObjCProtocolDecl *, 8> PotentialImplicitProtocols;
00829   
00830   for (ObjCProtocolDecl *ProtDecl : ObjCProtocolDecls)
00831     if (!ExplicitProtocols.count(ProtDecl))
00832       PotentialImplicitProtocols.push_back(ProtDecl);
00833   
00834   if (PotentialImplicitProtocols.empty())
00835     return;
00836 
00837   // go through list of non-optional methods and properties in each protocol
00838   // in the PotentialImplicitProtocols list. If class implements every one of the
00839   // methods and properties, then this class conforms to this protocol.
00840   llvm::SmallVector<ObjCProtocolDecl*, 8> ConformingProtocols;
00841   for (unsigned i = 0, e = PotentialImplicitProtocols.size(); i != e; i++)
00842     if (ClassImplementsAllMethodsAndProperties(Ctx, ImpDecl, IDecl,
00843                                               PotentialImplicitProtocols[i]))
00844       ConformingProtocols.push_back(PotentialImplicitProtocols[i]);
00845   
00846   if (ConformingProtocols.empty())
00847     return;
00848   
00849   // Further reduce number of conforming protocols. If protocol P1 is in the list
00850   // protocol P2 (P2<P1>), No need to include P1.
00851   llvm::SmallVector<ObjCProtocolDecl*, 8> MinimalConformingProtocols;
00852   for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
00853     bool DropIt = false;
00854     ObjCProtocolDecl *TargetPDecl = ConformingProtocols[i];
00855     for (unsigned i1 = 0, e1 = ConformingProtocols.size(); i1 != e1; i1++) {
00856       ObjCProtocolDecl *PDecl = ConformingProtocols[i1];
00857       if (PDecl == TargetPDecl)
00858         continue;
00859       if (PDecl->lookupProtocolNamed(
00860             TargetPDecl->getDeclName().getAsIdentifierInfo())) {
00861         DropIt = true;
00862         break;
00863       }
00864     }
00865     if (!DropIt)
00866       MinimalConformingProtocols.push_back(TargetPDecl);
00867   }
00868   if (MinimalConformingProtocols.empty())
00869     return;
00870   edit::Commit commit(*Editor);
00871   rewriteToObjCInterfaceDecl(IDecl, MinimalConformingProtocols,
00872                              *NSAPIObj, commit);
00873   Editor->commit(commit);
00874 }
00875 
00876 void ObjCMigrateASTConsumer::CacheObjCNSIntegerTypedefed(
00877                                           const TypedefDecl *TypedefDcl) {
00878   
00879   QualType qt = TypedefDcl->getTypeSourceInfo()->getType();
00880   if (NSAPIObj->isObjCNSIntegerType(qt))
00881     NSIntegerTypedefed = TypedefDcl;
00882   else if (NSAPIObj->isObjCNSUIntegerType(qt))
00883     NSUIntegerTypedefed = TypedefDcl;
00884 }
00885 
00886 bool ObjCMigrateASTConsumer::migrateNSEnumDecl(ASTContext &Ctx,
00887                                            const EnumDecl *EnumDcl,
00888                                            const TypedefDecl *TypedefDcl) {
00889   if (!EnumDcl->isCompleteDefinition() || EnumDcl->getIdentifier() ||
00890       EnumDcl->isDeprecated() || EnumDcl->getIntegerTypeSourceInfo())
00891     return false;
00892   if (!TypedefDcl) {
00893     if (NSIntegerTypedefed) {
00894       TypedefDcl = NSIntegerTypedefed;
00895       NSIntegerTypedefed = nullptr;
00896     }
00897     else if (NSUIntegerTypedefed) {
00898       TypedefDcl = NSUIntegerTypedefed;
00899       NSUIntegerTypedefed = nullptr;
00900     }
00901     else
00902       return false;
00903     FileID FileIdOfTypedefDcl =
00904       PP.getSourceManager().getFileID(TypedefDcl->getLocation());
00905     FileID FileIdOfEnumDcl =
00906       PP.getSourceManager().getFileID(EnumDcl->getLocation());
00907     if (FileIdOfTypedefDcl != FileIdOfEnumDcl)
00908       return false;
00909   }
00910   if (TypedefDcl->isDeprecated())
00911     return false;
00912   
00913   QualType qt = TypedefDcl->getTypeSourceInfo()->getType();
00914   StringRef NSIntegerName = NSAPIObj->GetNSIntegralKind(qt);
00915   
00916   if (NSIntegerName.empty()) {
00917     // Also check for typedef enum {...} TD;
00918     if (const EnumType *EnumTy = qt->getAs<EnumType>()) {
00919       if (EnumTy->getDecl() == EnumDcl) {
00920         bool NSOptions = UseNSOptionsMacro(PP, Ctx, EnumDcl);
00921         if (!InsertFoundation(Ctx, TypedefDcl->getLocStart()))
00922           return false;
00923         edit::Commit commit(*Editor);
00924         rewriteToNSMacroDecl(EnumDcl, TypedefDcl, *NSAPIObj, commit, !NSOptions);
00925         Editor->commit(commit);
00926         return true;
00927       }
00928     }
00929     return false;
00930   }
00931   
00932   // We may still use NS_OPTIONS based on what we find in the enumertor list.
00933   bool NSOptions = UseNSOptionsMacro(PP, Ctx, EnumDcl);
00934   if (!InsertFoundation(Ctx, TypedefDcl->getLocStart()))
00935     return false;
00936   edit::Commit commit(*Editor);
00937   bool Res = rewriteToNSEnumDecl(EnumDcl, TypedefDcl, *NSAPIObj,
00938                                  commit, NSIntegerName, NSOptions);
00939   Editor->commit(commit);
00940   return Res;
00941 }
00942 
00943 static void ReplaceWithInstancetype(ASTContext &Ctx,
00944                                     const ObjCMigrateASTConsumer &ASTC,
00945                                     ObjCMethodDecl *OM) {
00946   if (OM->getReturnType() == Ctx.getObjCInstanceType())
00947     return; // already has instancetype.
00948 
00949   SourceRange R;
00950   std::string ClassString;
00951   if (TypeSourceInfo *TSInfo = OM->getReturnTypeSourceInfo()) {
00952     TypeLoc TL = TSInfo->getTypeLoc();
00953     R = SourceRange(TL.getBeginLoc(), TL.getEndLoc());
00954     ClassString = "instancetype";
00955   }
00956   else {
00957     R = SourceRange(OM->getLocStart(), OM->getLocStart());
00958     ClassString = OM->isInstanceMethod() ? '-' : '+';
00959     ClassString += " (instancetype)";
00960   }
00961   edit::Commit commit(*ASTC.Editor);
00962   commit.replace(R, ClassString);
00963   ASTC.Editor->commit(commit);
00964 }
00965 
00966 static void ReplaceWithClasstype(const ObjCMigrateASTConsumer &ASTC,
00967                                     ObjCMethodDecl *OM) {
00968   ObjCInterfaceDecl *IDecl = OM->getClassInterface();
00969   SourceRange R;
00970   std::string ClassString;
00971   if (TypeSourceInfo *TSInfo = OM->getReturnTypeSourceInfo()) {
00972     TypeLoc TL = TSInfo->getTypeLoc();
00973     R = SourceRange(TL.getBeginLoc(), TL.getEndLoc()); {
00974       ClassString  = IDecl->getName();
00975       ClassString += "*";
00976     }
00977   }
00978   else {
00979     R = SourceRange(OM->getLocStart(), OM->getLocStart());
00980     ClassString = "+ (";
00981     ClassString += IDecl->getName(); ClassString += "*)";
00982   }
00983   edit::Commit commit(*ASTC.Editor);
00984   commit.replace(R, ClassString);
00985   ASTC.Editor->commit(commit);
00986 }
00987 
00988 void ObjCMigrateASTConsumer::migrateMethodInstanceType(ASTContext &Ctx,
00989                                                        ObjCContainerDecl *CDecl,
00990                                                        ObjCMethodDecl *OM) {
00991   ObjCInstanceTypeFamily OIT_Family =
00992     Selector::getInstTypeMethodFamily(OM->getSelector());
00993   
00994   std::string ClassName;
00995   switch (OIT_Family) {
00996     case OIT_None:
00997       migrateFactoryMethod(Ctx, CDecl, OM);
00998       return;
00999     case OIT_Array:
01000       ClassName = "NSArray";
01001       break;
01002     case OIT_Dictionary:
01003       ClassName = "NSDictionary";
01004       break;
01005     case OIT_Singleton:
01006       migrateFactoryMethod(Ctx, CDecl, OM, OIT_Singleton);
01007       return;
01008     case OIT_Init:
01009       if (OM->getReturnType()->isObjCIdType())
01010         ReplaceWithInstancetype(Ctx, *this, OM);
01011       return;
01012     case OIT_ReturnsSelf:
01013       migrateFactoryMethod(Ctx, CDecl, OM, OIT_ReturnsSelf);
01014       return;
01015   }
01016   if (!OM->getReturnType()->isObjCIdType())
01017     return;
01018   
01019   ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl);
01020   if (!IDecl) {
01021     if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl))
01022       IDecl = CatDecl->getClassInterface();
01023     else if (ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(CDecl))
01024       IDecl = ImpDecl->getClassInterface();
01025   }
01026   if (!IDecl ||
01027       !IDecl->lookupInheritedClass(&Ctx.Idents.get(ClassName))) {
01028     migrateFactoryMethod(Ctx, CDecl, OM);
01029     return;
01030   }
01031   ReplaceWithInstancetype(Ctx, *this, OM);
01032 }
01033 
01034 static bool TypeIsInnerPointer(QualType T) {
01035   if (!T->isAnyPointerType())
01036     return false;
01037   if (T->isObjCObjectPointerType() || T->isObjCBuiltinType() ||
01038       T->isBlockPointerType() || T->isFunctionPointerType() ||
01039       ento::coreFoundation::isCFObjectRef(T))
01040     return false;
01041   // Also, typedef-of-pointer-to-incomplete-struct is something that we assume
01042   // is not an innter pointer type.
01043   QualType OrigT = T;
01044   while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr()))
01045     T = TD->getDecl()->getUnderlyingType();
01046   if (OrigT == T || !T->isPointerType())
01047     return true;
01048   const PointerType* PT = T->getAs<PointerType>();
01049   QualType UPointeeT = PT->getPointeeType().getUnqualifiedType();
01050   if (UPointeeT->isRecordType()) {
01051     const RecordType *RecordTy = UPointeeT->getAs<RecordType>();
01052     if (!RecordTy->getDecl()->isCompleteDefinition())
01053       return false;
01054   }
01055   return true;
01056 }
01057 
01058 /// \brief Check whether the two versions match.
01059 static bool versionsMatch(const VersionTuple &X, const VersionTuple &Y) {
01060   return (X == Y);
01061 }
01062 
01063 /// AvailabilityAttrsMatch - This routine checks that if comparing two
01064 /// availability attributes, all their components match. It returns
01065 /// true, if not dealing with availability or when all components of
01066 /// availability attributes match. This routine is only called when
01067 /// the attributes are of the same kind.
01068 static bool AvailabilityAttrsMatch(Attr *At1, Attr *At2) {
01069   const AvailabilityAttr *AA1 = dyn_cast<AvailabilityAttr>(At1);
01070   if (!AA1)
01071     return true;
01072   const AvailabilityAttr *AA2 = dyn_cast<AvailabilityAttr>(At2);
01073   
01074   VersionTuple Introduced1 = AA1->getIntroduced();
01075   VersionTuple Deprecated1 = AA1->getDeprecated();
01076   VersionTuple Obsoleted1 = AA1->getObsoleted();
01077   bool IsUnavailable1 = AA1->getUnavailable();
01078   VersionTuple Introduced2 = AA2->getIntroduced();
01079   VersionTuple Deprecated2 = AA2->getDeprecated();
01080   VersionTuple Obsoleted2 = AA2->getObsoleted();
01081   bool IsUnavailable2 = AA2->getUnavailable();
01082   return (versionsMatch(Introduced1, Introduced2) &&
01083           versionsMatch(Deprecated1, Deprecated2) &&
01084           versionsMatch(Obsoleted1, Obsoleted2) &&
01085           IsUnavailable1 == IsUnavailable2);
01086   
01087 }
01088 
01089 static bool MatchTwoAttributeLists(const AttrVec &Attrs1, const AttrVec &Attrs2,
01090                                    bool &AvailabilityArgsMatch) {
01091   // This list is very small, so this need not be optimized.
01092   for (unsigned i = 0, e = Attrs1.size(); i != e; i++) {
01093     bool match = false;
01094     for (unsigned j = 0, f = Attrs2.size(); j != f; j++) {
01095       // Matching attribute kind only. Except for Availabilty attributes,
01096       // we are not getting into details of the attributes. For all practical purposes
01097       // this is sufficient.
01098       if (Attrs1[i]->getKind() == Attrs2[j]->getKind()) {
01099         if (AvailabilityArgsMatch)
01100           AvailabilityArgsMatch = AvailabilityAttrsMatch(Attrs1[i], Attrs2[j]);
01101         match = true;
01102         break;
01103       }
01104     }
01105     if (!match)
01106       return false;
01107   }
01108   return true;
01109 }
01110 
01111 /// AttributesMatch - This routine checks list of attributes for two
01112 /// decls. It returns false, if there is a mismatch in kind of
01113 /// attributes seen in the decls. It returns true if the two decls
01114 /// have list of same kind of attributes. Furthermore, when there
01115 /// are availability attributes in the two decls, it sets the
01116 /// AvailabilityArgsMatch to false if availability attributes have
01117 /// different versions, etc.
01118 static bool AttributesMatch(const Decl *Decl1, const Decl *Decl2,
01119                             bool &AvailabilityArgsMatch) {
01120   if (!Decl1->hasAttrs() || !Decl2->hasAttrs()) {
01121     AvailabilityArgsMatch = (Decl1->hasAttrs() == Decl2->hasAttrs());
01122     return true;
01123   }
01124   AvailabilityArgsMatch = true;
01125   const AttrVec &Attrs1 = Decl1->getAttrs();
01126   const AttrVec &Attrs2 = Decl2->getAttrs();
01127   bool match = MatchTwoAttributeLists(Attrs1, Attrs2, AvailabilityArgsMatch);
01128   if (match && (Attrs2.size() > Attrs1.size()))
01129     return MatchTwoAttributeLists(Attrs2, Attrs1, AvailabilityArgsMatch);
01130   return match;
01131 }
01132 
01133 static bool IsValidIdentifier(ASTContext &Ctx,
01134                               const char *Name) {
01135   if (!isIdentifierHead(Name[0]))
01136     return false;
01137   std::string NameString = Name;
01138   NameString[0] = toLowercase(NameString[0]);
01139   IdentifierInfo *II = &Ctx.Idents.get(NameString);
01140   return II->getTokenID() ==  tok::identifier;
01141 }
01142 
01143 bool ObjCMigrateASTConsumer::migrateProperty(ASTContext &Ctx,
01144                              ObjCContainerDecl *D,
01145                              ObjCMethodDecl *Method) {
01146   if (Method->isPropertyAccessor() || !Method->isInstanceMethod() ||
01147       Method->param_size() != 0)
01148     return false;
01149   // Is this method candidate to be a getter?
01150   QualType GRT = Method->getReturnType();
01151   if (GRT->isVoidType())
01152     return false;
01153   
01154   Selector GetterSelector = Method->getSelector();
01155   ObjCInstanceTypeFamily OIT_Family =
01156     Selector::getInstTypeMethodFamily(GetterSelector);
01157   
01158   if (OIT_Family != OIT_None)
01159     return false;
01160   
01161   IdentifierInfo *getterName = GetterSelector.getIdentifierInfoForSlot(0);
01162   Selector SetterSelector =
01163   SelectorTable::constructSetterSelector(PP.getIdentifierTable(),
01164                                          PP.getSelectorTable(),
01165                                          getterName);
01166   ObjCMethodDecl *SetterMethod = D->getInstanceMethod(SetterSelector);
01167   unsigned LengthOfPrefix = 0;
01168   if (!SetterMethod) {
01169     // try a different naming convention for getter: isXxxxx
01170     StringRef getterNameString = getterName->getName();
01171     bool IsPrefix = getterNameString.startswith("is");
01172     // Note that we don't want to change an isXXX method of retainable object
01173     // type to property (readonly or otherwise).
01174     if (IsPrefix && GRT->isObjCRetainableType())
01175       return false;
01176     if (IsPrefix || getterNameString.startswith("get")) {
01177       LengthOfPrefix = (IsPrefix ? 2 : 3);
01178       const char *CGetterName = getterNameString.data() + LengthOfPrefix;
01179       // Make sure that first character after "is" or "get" prefix can
01180       // start an identifier.
01181       if (!IsValidIdentifier(Ctx, CGetterName))
01182         return false;
01183       if (CGetterName[0] && isUppercase(CGetterName[0])) {
01184         getterName = &Ctx.Idents.get(CGetterName);
01185         SetterSelector =
01186         SelectorTable::constructSetterSelector(PP.getIdentifierTable(),
01187                                                PP.getSelectorTable(),
01188                                                getterName);
01189         SetterMethod = D->getInstanceMethod(SetterSelector);
01190       }
01191     }
01192   }
01193   
01194   if (SetterMethod) {
01195     if ((ASTMigrateActions & FrontendOptions::ObjCMT_ReadwriteProperty) == 0)
01196       return false;
01197     bool AvailabilityArgsMatch;
01198     if (SetterMethod->isDeprecated() ||
01199         !AttributesMatch(Method, SetterMethod, AvailabilityArgsMatch))
01200       return false;
01201     
01202     // Is this a valid setter, matching the target getter?
01203     QualType SRT = SetterMethod->getReturnType();
01204     if (!SRT->isVoidType())
01205       return false;
01206     const ParmVarDecl *argDecl = *SetterMethod->param_begin();
01207     QualType ArgType = argDecl->getType();
01208     if (!Ctx.hasSameUnqualifiedType(ArgType, GRT))
01209       return false;
01210     edit::Commit commit(*Editor);
01211     rewriteToObjCProperty(Method, SetterMethod, *NSAPIObj, commit,
01212                           LengthOfPrefix,
01213                           (ASTMigrateActions &
01214                            FrontendOptions::ObjCMT_AtomicProperty) != 0,
01215                           (ASTMigrateActions &
01216                            FrontendOptions::ObjCMT_NsAtomicIOSOnlyProperty) != 0,
01217                           AvailabilityArgsMatch);
01218     Editor->commit(commit);
01219     return true;
01220   }
01221   else if (ASTMigrateActions & FrontendOptions::ObjCMT_ReadonlyProperty) {
01222     // Try a non-void method with no argument (and no setter or property of same name
01223     // as a 'readonly' property.
01224     edit::Commit commit(*Editor);
01225     rewriteToObjCProperty(Method, nullptr /*SetterMethod*/, *NSAPIObj, commit,
01226                           LengthOfPrefix,
01227                           (ASTMigrateActions &
01228                            FrontendOptions::ObjCMT_AtomicProperty) != 0,
01229                           (ASTMigrateActions &
01230                            FrontendOptions::ObjCMT_NsAtomicIOSOnlyProperty) != 0,
01231                           /*AvailabilityArgsMatch*/false);
01232     Editor->commit(commit);
01233     return true;
01234   }
01235   return false;
01236 }
01237 
01238 void ObjCMigrateASTConsumer::migrateNsReturnsInnerPointer(ASTContext &Ctx,
01239                                                           ObjCMethodDecl *OM) {
01240   if (OM->isImplicit() ||
01241       !OM->isInstanceMethod() ||
01242       OM->hasAttr<ObjCReturnsInnerPointerAttr>())
01243     return;
01244 
01245   QualType RT = OM->getReturnType();
01246   if (!TypeIsInnerPointer(RT) ||
01247       !Ctx.Idents.get("NS_RETURNS_INNER_POINTER").hasMacroDefinition())
01248     return;
01249   
01250   edit::Commit commit(*Editor);
01251   commit.insertBefore(OM->getLocEnd(), " NS_RETURNS_INNER_POINTER");
01252   Editor->commit(commit);
01253 }
01254 
01255 void ObjCMigrateASTConsumer::migratePropertyNsReturnsInnerPointer(ASTContext &Ctx,
01256                                                                   ObjCPropertyDecl *P) {
01257   QualType T = P->getType();
01258   
01259   if (!TypeIsInnerPointer(T) ||
01260       !Ctx.Idents.get("NS_RETURNS_INNER_POINTER").hasMacroDefinition())
01261     return;
01262   edit::Commit commit(*Editor);
01263   commit.insertBefore(P->getLocEnd(), " NS_RETURNS_INNER_POINTER ");
01264   Editor->commit(commit);
01265 }
01266 
01267 void ObjCMigrateASTConsumer::migrateAllMethodInstaceType(ASTContext &Ctx,
01268                                                  ObjCContainerDecl *CDecl) {
01269   if (CDecl->isDeprecated() || IsCategoryNameWithDeprecatedSuffix(CDecl))
01270     return;
01271   
01272   // migrate methods which can have instancetype as their result type.
01273   for (auto *Method : CDecl->methods()) {
01274     if (Method->isDeprecated())
01275       continue;
01276     migrateMethodInstanceType(Ctx, CDecl, Method);
01277   }
01278 }
01279 
01280 void ObjCMigrateASTConsumer::migrateFactoryMethod(ASTContext &Ctx,
01281                                                   ObjCContainerDecl *CDecl,
01282                                                   ObjCMethodDecl *OM,
01283                                                   ObjCInstanceTypeFamily OIT_Family) {
01284   if (OM->isInstanceMethod() ||
01285       OM->getReturnType() == Ctx.getObjCInstanceType() ||
01286       !OM->getReturnType()->isObjCIdType())
01287     return;
01288   
01289   // Candidate factory methods are + (id) NaMeXXX : ... which belong to a class
01290   // NSYYYNamE with matching names be at least 3 characters long.
01291   ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl);
01292   if (!IDecl) {
01293     if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl))
01294       IDecl = CatDecl->getClassInterface();
01295     else if (ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(CDecl))
01296       IDecl = ImpDecl->getClassInterface();
01297   }
01298   if (!IDecl)
01299     return;
01300   
01301   std::string StringClassName = IDecl->getName();
01302   StringRef LoweredClassName(StringClassName);
01303   std::string StringLoweredClassName = LoweredClassName.lower();
01304   LoweredClassName = StringLoweredClassName;
01305   
01306   IdentifierInfo *MethodIdName = OM->getSelector().getIdentifierInfoForSlot(0);
01307   // Handle method with no name at its first selector slot; e.g. + (id):(int)x.
01308   if (!MethodIdName)
01309     return;
01310   
01311   std::string MethodName = MethodIdName->getName();
01312   if (OIT_Family == OIT_Singleton || OIT_Family == OIT_ReturnsSelf) {
01313     StringRef STRefMethodName(MethodName);
01314     size_t len = 0;
01315     if (STRefMethodName.startswith("standard"))
01316       len = strlen("standard");
01317     else if (STRefMethodName.startswith("shared"))
01318       len = strlen("shared");
01319     else if (STRefMethodName.startswith("default"))
01320       len = strlen("default");
01321     else
01322       return;
01323     MethodName = STRefMethodName.substr(len);
01324   }
01325   std::string MethodNameSubStr = MethodName.substr(0, 3);
01326   StringRef MethodNamePrefix(MethodNameSubStr);
01327   std::string StringLoweredMethodNamePrefix = MethodNamePrefix.lower();
01328   MethodNamePrefix = StringLoweredMethodNamePrefix;
01329   size_t Ix = LoweredClassName.rfind(MethodNamePrefix);
01330   if (Ix == StringRef::npos)
01331     return;
01332   std::string ClassNamePostfix = LoweredClassName.substr(Ix);
01333   StringRef LoweredMethodName(MethodName);
01334   std::string StringLoweredMethodName = LoweredMethodName.lower();
01335   LoweredMethodName = StringLoweredMethodName;
01336   if (!LoweredMethodName.startswith(ClassNamePostfix))
01337     return;
01338   if (OIT_Family == OIT_ReturnsSelf)
01339     ReplaceWithClasstype(*this, OM);
01340   else
01341     ReplaceWithInstancetype(Ctx, *this, OM);
01342 }
01343 
01344 static bool IsVoidStarType(QualType Ty) {
01345   if (!Ty->isPointerType())
01346     return false;
01347   
01348   while (const TypedefType *TD = dyn_cast<TypedefType>(Ty.getTypePtr()))
01349     Ty = TD->getDecl()->getUnderlyingType();
01350   
01351   // Is the type void*?
01352   const PointerType* PT = Ty->getAs<PointerType>();
01353   if (PT->getPointeeType().getUnqualifiedType()->isVoidType())
01354     return true;
01355   return IsVoidStarType(PT->getPointeeType());
01356 }
01357 
01358 /// AuditedType - This routine audits the type AT and returns false if it is one of known
01359 /// CF object types or of the "void *" variety. It returns true if we don't care about the type
01360 /// such as a non-pointer or pointers which have no ownership issues (such as "int *").
01361 static bool AuditedType (QualType AT) {
01362   if (!AT->isAnyPointerType() && !AT->isBlockPointerType())
01363     return true;
01364   // FIXME. There isn't much we can say about CF pointer type; or is there?
01365   if (ento::coreFoundation::isCFObjectRef(AT) ||
01366       IsVoidStarType(AT) ||
01367       // If an ObjC object is type, assuming that it is not a CF function and
01368       // that it is an un-audited function.
01369       AT->isObjCObjectPointerType() || AT->isObjCBuiltinType())
01370     return false;
01371   // All other pointers are assumed audited as harmless.
01372   return true;
01373 }
01374 
01375 void ObjCMigrateASTConsumer::AnnotateImplicitBridging(ASTContext &Ctx) {
01376   if (CFFunctionIBCandidates.empty())
01377     return;
01378   if (!Ctx.Idents.get("CF_IMPLICIT_BRIDGING_ENABLED").hasMacroDefinition()) {
01379     CFFunctionIBCandidates.clear();
01380     FileId = FileID();
01381     return;
01382   }
01383   // Insert CF_IMPLICIT_BRIDGING_ENABLE/CF_IMPLICIT_BRIDGING_DISABLED
01384   const Decl *FirstFD = CFFunctionIBCandidates[0];
01385   const Decl *LastFD  =
01386     CFFunctionIBCandidates[CFFunctionIBCandidates.size()-1];
01387   const char *PragmaString = "\nCF_IMPLICIT_BRIDGING_ENABLED\n\n";
01388   edit::Commit commit(*Editor);
01389   commit.insertBefore(FirstFD->getLocStart(), PragmaString);
01390   PragmaString = "\n\nCF_IMPLICIT_BRIDGING_DISABLED\n";
01391   SourceLocation EndLoc = LastFD->getLocEnd();
01392   // get location just past end of function location.
01393   EndLoc = PP.getLocForEndOfToken(EndLoc);
01394   if (isa<FunctionDecl>(LastFD)) {
01395     // For Methods, EndLoc points to the ending semcolon. So,
01396     // not of these extra work is needed.
01397     Token Tok;
01398     // get locaiton of token that comes after end of function.
01399     bool Failed = PP.getRawToken(EndLoc, Tok, /*IgnoreWhiteSpace=*/true);
01400     if (!Failed)
01401       EndLoc = Tok.getLocation();
01402   }
01403   commit.insertAfterToken(EndLoc, PragmaString);
01404   Editor->commit(commit);
01405   FileId = FileID();
01406   CFFunctionIBCandidates.clear();
01407 }
01408 
01409 void ObjCMigrateASTConsumer::migrateCFAnnotation(ASTContext &Ctx, const Decl *Decl) {
01410   if (Decl->isDeprecated())
01411     return;
01412   
01413   if (Decl->hasAttr<CFAuditedTransferAttr>()) {
01414     assert(CFFunctionIBCandidates.empty() &&
01415            "Cannot have audited functions/methods inside user "
01416            "provided CF_IMPLICIT_BRIDGING_ENABLE");
01417     return;
01418   }
01419   
01420   // Finction must be annotated first.
01421   if (const FunctionDecl *FuncDecl = dyn_cast<FunctionDecl>(Decl)) {
01422     CF_BRIDGING_KIND AuditKind = migrateAddFunctionAnnotation(Ctx, FuncDecl);
01423     if (AuditKind == CF_BRIDGING_ENABLE) {
01424       CFFunctionIBCandidates.push_back(Decl);
01425       if (FileId.isInvalid())
01426         FileId = PP.getSourceManager().getFileID(Decl->getLocation());
01427     }
01428     else if (AuditKind == CF_BRIDGING_MAY_INCLUDE) {
01429       if (!CFFunctionIBCandidates.empty()) {
01430         CFFunctionIBCandidates.push_back(Decl);
01431         if (FileId.isInvalid())
01432           FileId = PP.getSourceManager().getFileID(Decl->getLocation());
01433       }
01434     }
01435     else
01436       AnnotateImplicitBridging(Ctx);
01437   }
01438   else {
01439     migrateAddMethodAnnotation(Ctx, cast<ObjCMethodDecl>(Decl));
01440     AnnotateImplicitBridging(Ctx);
01441   }
01442 }
01443 
01444 void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
01445                                               const CallEffects &CE,
01446                                               const FunctionDecl *FuncDecl,
01447                                               bool ResultAnnotated) {
01448   // Annotate function.
01449   if (!ResultAnnotated) {
01450     RetEffect Ret = CE.getReturnValue();
01451     const char *AnnotationString = nullptr;
01452     if (Ret.getObjKind() == RetEffect::CF) {
01453       if (Ret.isOwned() &&
01454           Ctx.Idents.get("CF_RETURNS_RETAINED").hasMacroDefinition())
01455         AnnotationString = " CF_RETURNS_RETAINED";
01456       else if (Ret.notOwned() &&
01457                Ctx.Idents.get("CF_RETURNS_NOT_RETAINED").hasMacroDefinition())
01458         AnnotationString = " CF_RETURNS_NOT_RETAINED";
01459     }
01460     else if (Ret.getObjKind() == RetEffect::ObjC) {
01461       if (Ret.isOwned() &&
01462           Ctx.Idents.get("NS_RETURNS_RETAINED").hasMacroDefinition())
01463         AnnotationString = " NS_RETURNS_RETAINED";
01464     }
01465     
01466     if (AnnotationString) {
01467       edit::Commit commit(*Editor);
01468       commit.insertAfterToken(FuncDecl->getLocEnd(), AnnotationString);
01469       Editor->commit(commit);
01470     }
01471   }
01472   ArrayRef<ArgEffect> AEArgs = CE.getArgs();
01473   unsigned i = 0;
01474   for (FunctionDecl::param_const_iterator pi = FuncDecl->param_begin(),
01475        pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) {
01476     const ParmVarDecl *pd = *pi;
01477     ArgEffect AE = AEArgs[i];
01478     if (AE == DecRef && !pd->hasAttr<CFConsumedAttr>() &&
01479         Ctx.Idents.get("CF_CONSUMED").hasMacroDefinition()) {
01480       edit::Commit commit(*Editor);
01481       commit.insertBefore(pd->getLocation(), "CF_CONSUMED ");
01482       Editor->commit(commit);
01483     }
01484     else if (AE == DecRefMsg && !pd->hasAttr<NSConsumedAttr>() &&
01485              Ctx.Idents.get("NS_CONSUMED").hasMacroDefinition()) {
01486       edit::Commit commit(*Editor);
01487       commit.insertBefore(pd->getLocation(), "NS_CONSUMED ");
01488       Editor->commit(commit);
01489     }
01490   }
01491 }
01492 
01493 
01494 ObjCMigrateASTConsumer::CF_BRIDGING_KIND
01495   ObjCMigrateASTConsumer::migrateAddFunctionAnnotation(
01496                                                   ASTContext &Ctx,
01497                                                   const FunctionDecl *FuncDecl) {
01498   if (FuncDecl->hasBody())
01499     return CF_BRIDGING_NONE;
01500     
01501   CallEffects CE  = CallEffects::getEffect(FuncDecl);
01502   bool FuncIsReturnAnnotated = (FuncDecl->hasAttr<CFReturnsRetainedAttr>() ||
01503                                 FuncDecl->hasAttr<CFReturnsNotRetainedAttr>() ||
01504                                 FuncDecl->hasAttr<NSReturnsRetainedAttr>() ||
01505                                 FuncDecl->hasAttr<NSReturnsNotRetainedAttr>() ||
01506                                 FuncDecl->hasAttr<NSReturnsAutoreleasedAttr>());
01507   
01508   // Trivial case of when funciton is annotated and has no argument.
01509   if (FuncIsReturnAnnotated && FuncDecl->getNumParams() == 0)
01510     return CF_BRIDGING_NONE;
01511   
01512   bool ReturnCFAudited = false;
01513   if (!FuncIsReturnAnnotated) {
01514     RetEffect Ret = CE.getReturnValue();
01515     if (Ret.getObjKind() == RetEffect::CF &&
01516         (Ret.isOwned() || Ret.notOwned()))
01517       ReturnCFAudited = true;
01518     else if (!AuditedType(FuncDecl->getReturnType()))
01519       return CF_BRIDGING_NONE;
01520   }
01521   
01522   // At this point result type is audited for potential inclusion.
01523   // Now, how about argument types.
01524   ArrayRef<ArgEffect> AEArgs = CE.getArgs();
01525   unsigned i = 0;
01526   bool ArgCFAudited = false;
01527   for (FunctionDecl::param_const_iterator pi = FuncDecl->param_begin(),
01528        pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) {
01529     const ParmVarDecl *pd = *pi;
01530     ArgEffect AE = AEArgs[i];
01531     if (AE == DecRef /*CFConsumed annotated*/ || AE == IncRef) {
01532       if (AE == DecRef && !pd->hasAttr<CFConsumedAttr>())
01533         ArgCFAudited = true;
01534       else if (AE == IncRef)
01535         ArgCFAudited = true;
01536     }
01537     else {
01538       QualType AT = pd->getType();
01539       if (!AuditedType(AT)) {
01540         AddCFAnnotations(Ctx, CE, FuncDecl, FuncIsReturnAnnotated);
01541         return CF_BRIDGING_NONE;
01542       }
01543     }
01544   }
01545   if (ReturnCFAudited || ArgCFAudited)
01546     return CF_BRIDGING_ENABLE;
01547   
01548   return CF_BRIDGING_MAY_INCLUDE;
01549 }
01550 
01551 void ObjCMigrateASTConsumer::migrateARCSafeAnnotation(ASTContext &Ctx,
01552                                                  ObjCContainerDecl *CDecl) {
01553   if (!isa<ObjCInterfaceDecl>(CDecl) || CDecl->isDeprecated())
01554     return;
01555   
01556   // migrate methods which can have instancetype as their result type.
01557   for (const auto *Method : CDecl->methods())
01558     migrateCFAnnotation(Ctx, Method);
01559 }
01560 
01561 void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
01562                                               const CallEffects &CE,
01563                                               const ObjCMethodDecl *MethodDecl,
01564                                               bool ResultAnnotated) {
01565   // Annotate function.
01566   if (!ResultAnnotated) {
01567     RetEffect Ret = CE.getReturnValue();
01568     const char *AnnotationString = nullptr;
01569     if (Ret.getObjKind() == RetEffect::CF) {
01570       if (Ret.isOwned() &&
01571           Ctx.Idents.get("CF_RETURNS_RETAINED").hasMacroDefinition())
01572         AnnotationString = " CF_RETURNS_RETAINED";
01573       else if (Ret.notOwned() &&
01574                Ctx.Idents.get("CF_RETURNS_NOT_RETAINED").hasMacroDefinition())
01575         AnnotationString = " CF_RETURNS_NOT_RETAINED";
01576     }
01577     else if (Ret.getObjKind() == RetEffect::ObjC) {
01578       ObjCMethodFamily OMF = MethodDecl->getMethodFamily();
01579       switch (OMF) {
01580         case clang::OMF_alloc:
01581         case clang::OMF_new:
01582         case clang::OMF_copy:
01583         case clang::OMF_init:
01584         case clang::OMF_mutableCopy:
01585           break;
01586           
01587         default:
01588           if (Ret.isOwned() &&
01589               Ctx.Idents.get("NS_RETURNS_RETAINED").hasMacroDefinition())
01590             AnnotationString = " NS_RETURNS_RETAINED";
01591           break;
01592       }
01593     }
01594     
01595     if (AnnotationString) {
01596       edit::Commit commit(*Editor);
01597       commit.insertBefore(MethodDecl->getLocEnd(), AnnotationString);
01598       Editor->commit(commit);
01599     }
01600   }
01601   ArrayRef<ArgEffect> AEArgs = CE.getArgs();
01602   unsigned i = 0;
01603   for (ObjCMethodDecl::param_const_iterator pi = MethodDecl->param_begin(),
01604        pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) {
01605     const ParmVarDecl *pd = *pi;
01606     ArgEffect AE = AEArgs[i];
01607     if (AE == DecRef && !pd->hasAttr<CFConsumedAttr>() &&
01608         Ctx.Idents.get("CF_CONSUMED").hasMacroDefinition()) {
01609       edit::Commit commit(*Editor);
01610       commit.insertBefore(pd->getLocation(), "CF_CONSUMED ");
01611       Editor->commit(commit);
01612     }
01613   }
01614 }
01615 
01616 void ObjCMigrateASTConsumer::migrateAddMethodAnnotation(
01617                                             ASTContext &Ctx,
01618                                             const ObjCMethodDecl *MethodDecl) {
01619   if (MethodDecl->hasBody() || MethodDecl->isImplicit())
01620     return;
01621   
01622   CallEffects CE  = CallEffects::getEffect(MethodDecl);
01623   bool MethodIsReturnAnnotated = (MethodDecl->hasAttr<CFReturnsRetainedAttr>() ||
01624                                   MethodDecl->hasAttr<CFReturnsNotRetainedAttr>() ||
01625                                   MethodDecl->hasAttr<NSReturnsRetainedAttr>() ||
01626                                   MethodDecl->hasAttr<NSReturnsNotRetainedAttr>() ||
01627                                   MethodDecl->hasAttr<NSReturnsAutoreleasedAttr>());
01628   
01629   if (CE.getReceiver() ==  DecRefMsg &&
01630       !MethodDecl->hasAttr<NSConsumesSelfAttr>() &&
01631       MethodDecl->getMethodFamily() != OMF_init &&
01632       MethodDecl->getMethodFamily() != OMF_release &&
01633       Ctx.Idents.get("NS_CONSUMES_SELF").hasMacroDefinition()) {
01634     edit::Commit commit(*Editor);
01635     commit.insertBefore(MethodDecl->getLocEnd(), " NS_CONSUMES_SELF");
01636     Editor->commit(commit);
01637   }
01638   
01639   // Trivial case of when funciton is annotated and has no argument.
01640   if (MethodIsReturnAnnotated &&
01641       (MethodDecl->param_begin() == MethodDecl->param_end()))
01642     return;
01643   
01644   if (!MethodIsReturnAnnotated) {
01645     RetEffect Ret = CE.getReturnValue();
01646     if ((Ret.getObjKind() == RetEffect::CF ||
01647          Ret.getObjKind() == RetEffect::ObjC) &&
01648         (Ret.isOwned() || Ret.notOwned())) {
01649       AddCFAnnotations(Ctx, CE, MethodDecl, false);
01650       return;
01651     } else if (!AuditedType(MethodDecl->getReturnType()))
01652       return;
01653   }
01654   
01655   // At this point result type is either annotated or audited.
01656   // Now, how about argument types.
01657   ArrayRef<ArgEffect> AEArgs = CE.getArgs();
01658   unsigned i = 0;
01659   for (ObjCMethodDecl::param_const_iterator pi = MethodDecl->param_begin(),
01660        pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) {
01661     const ParmVarDecl *pd = *pi;
01662     ArgEffect AE = AEArgs[i];
01663     if ((AE == DecRef && !pd->hasAttr<CFConsumedAttr>()) || AE == IncRef ||
01664         !AuditedType(pd->getType())) {
01665       AddCFAnnotations(Ctx, CE, MethodDecl, MethodIsReturnAnnotated);
01666       return;
01667     }
01668   }
01669   return;
01670 }
01671 
01672 namespace {
01673 class SuperInitChecker : public RecursiveASTVisitor<SuperInitChecker> {
01674 public:
01675   bool shouldVisitTemplateInstantiations() const { return false; }
01676   bool shouldWalkTypesOfTypeLocs() const { return false; }
01677 
01678   bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
01679     if (E->getReceiverKind() == ObjCMessageExpr::SuperInstance) {
01680       if (E->getMethodFamily() == OMF_init)
01681         return false;
01682     }
01683     return true;
01684   }
01685 };
01686 } // anonymous namespace
01687 
01688 static bool hasSuperInitCall(const ObjCMethodDecl *MD) {
01689   return !SuperInitChecker().TraverseStmt(MD->getBody());
01690 }
01691 
01692 void ObjCMigrateASTConsumer::inferDesignatedInitializers(
01693     ASTContext &Ctx,
01694     const ObjCImplementationDecl *ImplD) {
01695 
01696   const ObjCInterfaceDecl *IFace = ImplD->getClassInterface();
01697   if (!IFace || IFace->hasDesignatedInitializers())
01698     return;
01699   if (!Ctx.Idents.get("NS_DESIGNATED_INITIALIZER").hasMacroDefinition())
01700     return;
01701 
01702   for (const auto *MD : ImplD->instance_methods()) {
01703     if (MD->isDeprecated() ||
01704         MD->getMethodFamily() != OMF_init ||
01705         MD->isDesignatedInitializerForTheInterface())
01706       continue;
01707     const ObjCMethodDecl *IFaceM = IFace->getMethod(MD->getSelector(),
01708                                                     /*isInstance=*/true);
01709     if (!IFaceM)
01710       continue;
01711     if (hasSuperInitCall(MD)) {
01712       edit::Commit commit(*Editor);
01713       commit.insert(IFaceM->getLocEnd(), " NS_DESIGNATED_INITIALIZER");
01714       Editor->commit(commit);
01715     }
01716   }
01717 }
01718 
01719 bool ObjCMigrateASTConsumer::InsertFoundation(ASTContext &Ctx,
01720                                               SourceLocation  Loc) {
01721   if (FoundationIncluded)
01722     return true;
01723   if (Loc.isInvalid())
01724     return false;
01725   edit::Commit commit(*Editor);
01726   if (Ctx.getLangOpts().Modules)
01727     commit.insert(Loc, "#ifndef NS_ENUM\n@import Foundation;\n#endif\n");
01728   else
01729     commit.insert(Loc, "#ifndef NS_ENUM\n#import <Foundation/Foundation.h>\n#endif\n");
01730   Editor->commit(commit);
01731   FoundationIncluded = true;
01732   return true;
01733 }
01734 
01735 namespace {
01736 
01737 class RewritesReceiver : public edit::EditsReceiver {
01738   Rewriter &Rewrite;
01739 
01740 public:
01741   RewritesReceiver(Rewriter &Rewrite) : Rewrite(Rewrite) { }
01742 
01743   void insert(SourceLocation loc, StringRef text) override {
01744     Rewrite.InsertText(loc, text);
01745   }
01746   void replace(CharSourceRange range, StringRef text) override {
01747     Rewrite.ReplaceText(range.getBegin(), Rewrite.getRangeSize(range), text);
01748   }
01749 };
01750 
01751 class JSONEditWriter : public edit::EditsReceiver {
01752   SourceManager &SourceMgr;
01753   llvm::raw_ostream &OS;
01754 
01755 public:
01756   JSONEditWriter(SourceManager &SM, llvm::raw_ostream &OS)
01757     : SourceMgr(SM), OS(OS) {
01758     OS << "[\n";
01759   }
01760   ~JSONEditWriter() {
01761     OS << "]\n";
01762   }
01763 
01764 private:
01765   struct EntryWriter {
01766     SourceManager &SourceMgr;
01767     llvm::raw_ostream &OS;
01768 
01769     EntryWriter(SourceManager &SM, llvm::raw_ostream &OS)
01770       : SourceMgr(SM), OS(OS) {
01771       OS << " {\n";
01772     }
01773     ~EntryWriter() {
01774       OS << " },\n";
01775     }
01776 
01777     void writeLoc(SourceLocation Loc) {
01778       FileID FID;
01779       unsigned Offset;
01780       std::tie(FID, Offset) = SourceMgr.getDecomposedLoc(Loc);
01781       assert(!FID.isInvalid());
01782       SmallString<200> Path =
01783           StringRef(SourceMgr.getFileEntryForID(FID)->getName());
01784       llvm::sys::fs::make_absolute(Path);
01785       OS << "  \"file\": \"";
01786       OS.write_escaped(Path.str()) << "\",\n";
01787       OS << "  \"offset\": " << Offset << ",\n";
01788     }
01789 
01790     void writeRemove(CharSourceRange Range) {
01791       assert(Range.isCharRange());
01792       std::pair<FileID, unsigned> Begin =
01793           SourceMgr.getDecomposedLoc(Range.getBegin());
01794       std::pair<FileID, unsigned> End =
01795           SourceMgr.getDecomposedLoc(Range.getEnd());
01796       assert(Begin.first == End.first);
01797       assert(Begin.second <= End.second);
01798       unsigned Length = End.second - Begin.second;
01799 
01800       OS << "  \"remove\": " << Length << ",\n";
01801     }
01802 
01803     void writeText(StringRef Text) {
01804       OS << "  \"text\": \"";
01805       OS.write_escaped(Text) << "\",\n";
01806     }
01807   };
01808  
01809   void insert(SourceLocation Loc, StringRef Text) override {
01810     EntryWriter Writer(SourceMgr, OS);
01811     Writer.writeLoc(Loc);
01812     Writer.writeText(Text);
01813   }
01814 
01815   void replace(CharSourceRange Range, StringRef Text) override {
01816     EntryWriter Writer(SourceMgr, OS);
01817     Writer.writeLoc(Range.getBegin());
01818     Writer.writeRemove(Range);
01819     Writer.writeText(Text);
01820   }
01821 
01822   void remove(CharSourceRange Range) override {
01823     EntryWriter Writer(SourceMgr, OS);
01824     Writer.writeLoc(Range.getBegin());
01825     Writer.writeRemove(Range);
01826   }
01827 };
01828 
01829 }
01830 
01831 void ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) {
01832   
01833   TranslationUnitDecl *TU = Ctx.getTranslationUnitDecl();
01834   if (ASTMigrateActions & FrontendOptions::ObjCMT_MigrateDecls) {
01835     for (DeclContext::decl_iterator D = TU->decls_begin(), DEnd = TU->decls_end();
01836          D != DEnd; ++D) {
01837       FileID FID = PP.getSourceManager().getFileID((*D)->getLocation());
01838       if (!FID.isInvalid())
01839         if (!FileId.isInvalid() && FileId != FID) {
01840           if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation)
01841             AnnotateImplicitBridging(Ctx);
01842         }
01843       
01844       if (ObjCInterfaceDecl *CDecl = dyn_cast<ObjCInterfaceDecl>(*D))
01845         if (canModify(CDecl))
01846           migrateObjCInterfaceDecl(Ctx, CDecl);
01847       if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(*D)) {
01848         if (canModify(CatDecl))
01849           migrateObjCInterfaceDecl(Ctx, CatDecl);
01850       }
01851       else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(*D))
01852         ObjCProtocolDecls.insert(PDecl->getCanonicalDecl());
01853       else if (const ObjCImplementationDecl *ImpDecl =
01854                dyn_cast<ObjCImplementationDecl>(*D)) {
01855         if ((ASTMigrateActions & FrontendOptions::ObjCMT_ProtocolConformance) &&
01856             canModify(ImpDecl))
01857           migrateProtocolConformance(Ctx, ImpDecl);
01858       }
01859       else if (const EnumDecl *ED = dyn_cast<EnumDecl>(*D)) {
01860         if (!(ASTMigrateActions & FrontendOptions::ObjCMT_NsMacros))
01861           continue;
01862         if (!canModify(ED))
01863           continue;
01864         DeclContext::decl_iterator N = D;
01865         if (++N != DEnd) {
01866           const TypedefDecl *TD = dyn_cast<TypedefDecl>(*N);
01867           if (migrateNSEnumDecl(Ctx, ED, TD) && TD)
01868             D++;
01869         }
01870         else
01871           migrateNSEnumDecl(Ctx, ED, /*TypedefDecl */nullptr);
01872       }
01873       else if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(*D)) {
01874         if (!(ASTMigrateActions & FrontendOptions::ObjCMT_NsMacros))
01875           continue;
01876         if (!canModify(TD))
01877           continue;
01878         DeclContext::decl_iterator N = D;
01879         if (++N == DEnd)
01880           continue;
01881         if (const EnumDecl *ED = dyn_cast<EnumDecl>(*N)) {
01882           if (++N != DEnd)
01883             if (const TypedefDecl *TDF = dyn_cast<TypedefDecl>(*N)) {
01884               // prefer typedef-follows-enum to enum-follows-typedef pattern.
01885               if (migrateNSEnumDecl(Ctx, ED, TDF)) {
01886                 ++D; ++D;
01887                 CacheObjCNSIntegerTypedefed(TD);
01888                 continue;
01889               }
01890             }
01891           if (migrateNSEnumDecl(Ctx, ED, TD)) {
01892             ++D;
01893             continue;
01894           }
01895         }
01896         CacheObjCNSIntegerTypedefed(TD);
01897       }
01898       else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*D)) {
01899         if ((ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) &&
01900             canModify(FD))
01901           migrateCFAnnotation(Ctx, FD);
01902       }
01903       
01904       if (ObjCContainerDecl *CDecl = dyn_cast<ObjCContainerDecl>(*D)) {
01905         bool CanModify = canModify(CDecl);
01906         // migrate methods which can have instancetype as their result type.
01907         if ((ASTMigrateActions & FrontendOptions::ObjCMT_Instancetype) &&
01908             CanModify)
01909           migrateAllMethodInstaceType(Ctx, CDecl);
01910         // annotate methods with CF annotations.
01911         if ((ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) &&
01912             CanModify)
01913           migrateARCSafeAnnotation(Ctx, CDecl);
01914       }
01915 
01916       if (const ObjCImplementationDecl *
01917             ImplD = dyn_cast<ObjCImplementationDecl>(*D)) {
01918         if ((ASTMigrateActions & FrontendOptions::ObjCMT_DesignatedInitializer) &&
01919             canModify(ImplD))
01920           inferDesignatedInitializers(Ctx, ImplD);
01921       }
01922     }
01923     if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation)
01924       AnnotateImplicitBridging(Ctx);
01925   }
01926   
01927  if (IsOutputFile) {
01928    std::error_code EC;
01929    llvm::raw_fd_ostream OS(MigrateDir, EC, llvm::sys::fs::F_None);
01930    if (EC) {
01931       DiagnosticsEngine &Diags = Ctx.getDiagnostics();
01932       Diags.Report(Diags.getCustomDiagID(DiagnosticsEngine::Error, "%0"))
01933           << EC.message();
01934       return;
01935     }
01936 
01937    JSONEditWriter Writer(Ctx.getSourceManager(), OS);
01938    Editor->applyRewrites(Writer);
01939    return;
01940  }
01941 
01942   Rewriter rewriter(Ctx.getSourceManager(), Ctx.getLangOpts());
01943   RewritesReceiver Rec(rewriter);
01944   Editor->applyRewrites(Rec);
01945 
01946   for (Rewriter::buffer_iterator
01947         I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) {
01948     FileID FID = I->first;
01949     RewriteBuffer &buf = I->second;
01950     const FileEntry *file = Ctx.getSourceManager().getFileEntryForID(FID);
01951     assert(file);
01952     SmallString<512> newText;
01953     llvm::raw_svector_ostream vecOS(newText);
01954     buf.write(vecOS);
01955     vecOS.flush();
01956     std::unique_ptr<llvm::MemoryBuffer> memBuf(
01957         llvm::MemoryBuffer::getMemBufferCopy(
01958             StringRef(newText.data(), newText.size()), file->getName()));
01959     SmallString<64> filePath(file->getName());
01960     FileMgr.FixupRelativePath(filePath);
01961     Remapper.remap(filePath.str(), std::move(memBuf));
01962   }
01963 
01964   if (IsOutputFile) {
01965     Remapper.flushToFile(MigrateDir, Ctx.getDiagnostics());
01966   } else {
01967     Remapper.flushToDisk(MigrateDir, Ctx.getDiagnostics());
01968   }
01969 }
01970 
01971 bool MigrateSourceAction::BeginInvocation(CompilerInstance &CI) {
01972   CI.getDiagnostics().setIgnoreAllWarnings(true);
01973   return true;
01974 }
01975 
01976 static std::vector<std::string> getWhiteListFilenames(StringRef DirPath) {
01977   using namespace llvm::sys::fs;
01978   using namespace llvm::sys::path;
01979 
01980   std::vector<std::string> Filenames;
01981   if (DirPath.empty() || !is_directory(DirPath))
01982     return Filenames;
01983 
01984   std::error_code EC;
01985   directory_iterator DI = directory_iterator(DirPath, EC);
01986   directory_iterator DE;
01987   for (; !EC && DI != DE; DI = DI.increment(EC)) {
01988     if (is_regular_file(DI->path()))
01989       Filenames.push_back(filename(DI->path()));
01990   }
01991 
01992   return Filenames;
01993 }
01994 
01995 std::unique_ptr<ASTConsumer>
01996 MigrateSourceAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
01997   PPConditionalDirectiveRecord *
01998     PPRec = new PPConditionalDirectiveRecord(CI.getSourceManager());
01999   unsigned ObjCMTAction = CI.getFrontendOpts().ObjCMTAction;
02000   unsigned ObjCMTOpts = ObjCMTAction;
02001   // These are companion flags, they do not enable transformations.
02002   ObjCMTOpts &= ~(FrontendOptions::ObjCMT_AtomicProperty |
02003                   FrontendOptions::ObjCMT_NsAtomicIOSOnlyProperty);
02004   if (ObjCMTOpts == FrontendOptions::ObjCMT_None) {
02005     // If no specific option was given, enable literals+subscripting transforms
02006     // by default.
02007     ObjCMTAction |= FrontendOptions::ObjCMT_Literals |
02008                     FrontendOptions::ObjCMT_Subscripting;
02009   }
02010   CI.getPreprocessor().addPPCallbacks(std::unique_ptr<PPCallbacks>(PPRec));
02011   std::vector<std::string> WhiteList =
02012     getWhiteListFilenames(CI.getFrontendOpts().ObjCMTWhiteListPath);
02013   return llvm::make_unique<ObjCMigrateASTConsumer>(
02014       CI.getFrontendOpts().OutputFile, ObjCMTAction, Remapper,
02015       CI.getFileManager(), PPRec, CI.getPreprocessor(),
02016       /*isOutputFile=*/true, WhiteList);
02017 }
02018 
02019 namespace {
02020 struct EditEntry {
02021   const FileEntry *File;
02022   unsigned Offset;
02023   unsigned RemoveLen;
02024   std::string Text;
02025 
02026   EditEntry() : File(), Offset(), RemoveLen() {}
02027 };
02028 }
02029 
02030 namespace llvm {
02031 template<> struct DenseMapInfo<EditEntry> {
02032   static inline EditEntry getEmptyKey() {
02033     EditEntry Entry;
02034     Entry.Offset = unsigned(-1);
02035     return Entry;
02036   }
02037   static inline EditEntry getTombstoneKey() {
02038     EditEntry Entry;
02039     Entry.Offset = unsigned(-2);
02040     return Entry;
02041   }
02042   static unsigned getHashValue(const EditEntry& Val) {
02043     llvm::FoldingSetNodeID ID;
02044     ID.AddPointer(Val.File);
02045     ID.AddInteger(Val.Offset);
02046     ID.AddInteger(Val.RemoveLen);
02047     ID.AddString(Val.Text);
02048     return ID.ComputeHash();
02049   }
02050   static bool isEqual(const EditEntry &LHS, const EditEntry &RHS) {
02051     return LHS.File == RHS.File &&
02052         LHS.Offset == RHS.Offset &&
02053         LHS.RemoveLen == RHS.RemoveLen &&
02054         LHS.Text == RHS.Text;
02055   }
02056 };
02057 }
02058 
02059 namespace {
02060 class RemapFileParser {
02061   FileManager &FileMgr;
02062 
02063 public:
02064   RemapFileParser(FileManager &FileMgr) : FileMgr(FileMgr) { }
02065 
02066   bool parse(StringRef File, SmallVectorImpl<EditEntry> &Entries) {
02067     using namespace llvm::yaml;
02068 
02069     llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
02070         llvm::MemoryBuffer::getFile(File);
02071     if (!FileBufOrErr)
02072       return true;
02073 
02074     llvm::SourceMgr SM;
02075     Stream YAMLStream(FileBufOrErr.get()->getMemBufferRef(), SM);
02076     document_iterator I = YAMLStream.begin();
02077     if (I == YAMLStream.end())
02078       return true;
02079     Node *Root = I->getRoot();
02080     if (!Root)
02081       return true;
02082 
02083     SequenceNode *SeqNode = dyn_cast<SequenceNode>(Root);
02084     if (!SeqNode)
02085       return true;
02086 
02087     for (SequenceNode::iterator
02088            AI = SeqNode->begin(), AE = SeqNode->end(); AI != AE; ++AI) {
02089       MappingNode *MapNode = dyn_cast<MappingNode>(&*AI);
02090       if (!MapNode)
02091         continue;
02092       parseEdit(MapNode, Entries);
02093     }
02094 
02095     return false;
02096   }
02097 
02098 private:
02099   void parseEdit(llvm::yaml::MappingNode *Node,
02100                  SmallVectorImpl<EditEntry> &Entries) {
02101     using namespace llvm::yaml;
02102     EditEntry Entry;
02103     bool Ignore = false;
02104 
02105     for (MappingNode::iterator
02106            KVI = Node->begin(), KVE = Node->end(); KVI != KVE; ++KVI) {
02107       ScalarNode *KeyString = dyn_cast<ScalarNode>((*KVI).getKey());
02108       if (!KeyString)
02109         continue;
02110       SmallString<10> KeyStorage;
02111       StringRef Key = KeyString->getValue(KeyStorage);
02112 
02113       ScalarNode *ValueString = dyn_cast<ScalarNode>((*KVI).getValue());
02114       if (!ValueString)
02115         continue;
02116       SmallString<64> ValueStorage;
02117       StringRef Val = ValueString->getValue(ValueStorage);
02118 
02119       if (Key == "file") {
02120         const FileEntry *FE = FileMgr.getFile(Val);
02121         if (!FE)
02122           Ignore = true;
02123         Entry.File = FE;
02124       } else if (Key == "offset") {
02125         if (Val.getAsInteger(10, Entry.Offset))
02126           Ignore = true;
02127       } else if (Key == "remove") {
02128         if (Val.getAsInteger(10, Entry.RemoveLen))
02129           Ignore = true;
02130       } else if (Key == "text") {
02131         Entry.Text = Val;
02132       }
02133     }
02134 
02135     if (!Ignore)
02136       Entries.push_back(Entry);
02137   }
02138 };
02139 }
02140 
02141 static bool reportDiag(const Twine &Err, DiagnosticsEngine &Diag) {
02142   Diag.Report(Diag.getCustomDiagID(DiagnosticsEngine::Error, "%0"))
02143       << Err.str();
02144   return true;
02145 }
02146 
02147 static std::string applyEditsToTemp(const FileEntry *FE,
02148                                     ArrayRef<EditEntry> Edits,
02149                                     FileManager &FileMgr,
02150                                     DiagnosticsEngine &Diag) {
02151   using namespace llvm::sys;
02152 
02153   SourceManager SM(Diag, FileMgr);
02154   FileID FID = SM.createFileID(FE, SourceLocation(), SrcMgr::C_User);
02155   LangOptions LangOpts;
02156   edit::EditedSource Editor(SM, LangOpts);
02157   for (ArrayRef<EditEntry>::iterator
02158         I = Edits.begin(), E = Edits.end(); I != E; ++I) {
02159     const EditEntry &Entry = *I;
02160     assert(Entry.File == FE);
02161     SourceLocation Loc =
02162         SM.getLocForStartOfFile(FID).getLocWithOffset(Entry.Offset);
02163     CharSourceRange Range;
02164     if (Entry.RemoveLen != 0) {
02165       Range = CharSourceRange::getCharRange(Loc,
02166                                          Loc.getLocWithOffset(Entry.RemoveLen));
02167     }
02168 
02169     edit::Commit commit(Editor);
02170     if (Range.isInvalid()) {
02171       commit.insert(Loc, Entry.Text);
02172     } else if (Entry.Text.empty()) {
02173       commit.remove(Range);
02174     } else {
02175       commit.replace(Range, Entry.Text);
02176     }
02177     Editor.commit(commit);
02178   }
02179 
02180   Rewriter rewriter(SM, LangOpts);
02181   RewritesReceiver Rec(rewriter);
02182   Editor.applyRewrites(Rec);
02183 
02184   const RewriteBuffer *Buf = rewriter.getRewriteBufferFor(FID);
02185   SmallString<512> NewText;
02186   llvm::raw_svector_ostream OS(NewText);
02187   Buf->write(OS);
02188   OS.flush();
02189 
02190   SmallString<64> TempPath;
02191   int FD;
02192   if (fs::createTemporaryFile(path::filename(FE->getName()),
02193                               path::extension(FE->getName()), FD,
02194                               TempPath)) {
02195     reportDiag("Could not create file: " + TempPath.str(), Diag);
02196     return std::string();
02197   }
02198 
02199   llvm::raw_fd_ostream TmpOut(FD, /*shouldClose=*/true);
02200   TmpOut.write(NewText.data(), NewText.size());
02201   TmpOut.close();
02202 
02203   return TempPath.str();
02204 }
02205 
02206 bool arcmt::getFileRemappingsFromFileList(
02207                         std::vector<std::pair<std::string,std::string> > &remap,
02208                         ArrayRef<StringRef> remapFiles,
02209                         DiagnosticConsumer *DiagClient) {
02210   bool hasErrorOccurred = false;
02211 
02212   FileSystemOptions FSOpts;
02213   FileManager FileMgr(FSOpts);
02214   RemapFileParser Parser(FileMgr);
02215 
02216   IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
02217   IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
02218       new DiagnosticsEngine(DiagID, new DiagnosticOptions,
02219                             DiagClient, /*ShouldOwnClient=*/false));
02220 
02221   typedef llvm::DenseMap<const FileEntry *, std::vector<EditEntry> >
02222       FileEditEntriesTy;
02223   FileEditEntriesTy FileEditEntries;
02224 
02225   llvm::DenseSet<EditEntry> EntriesSet;
02226 
02227   for (ArrayRef<StringRef>::iterator
02228          I = remapFiles.begin(), E = remapFiles.end(); I != E; ++I) {
02229     SmallVector<EditEntry, 16> Entries;
02230     if (Parser.parse(*I, Entries))
02231       continue;
02232 
02233     for (SmallVectorImpl<EditEntry>::iterator
02234            EI = Entries.begin(), EE = Entries.end(); EI != EE; ++EI) {
02235       EditEntry &Entry = *EI;
02236       if (!Entry.File)
02237         continue;
02238       std::pair<llvm::DenseSet<EditEntry>::iterator, bool>
02239         Insert = EntriesSet.insert(Entry);
02240       if (!Insert.second)
02241         continue;
02242 
02243       FileEditEntries[Entry.File].push_back(Entry);
02244     }
02245   }
02246 
02247   for (FileEditEntriesTy::iterator
02248          I = FileEditEntries.begin(), E = FileEditEntries.end(); I != E; ++I) {
02249     std::string TempFile = applyEditsToTemp(I->first, I->second,
02250                                             FileMgr, *Diags);
02251     if (TempFile.empty()) {
02252       hasErrorOccurred = true;
02253       continue;
02254     }
02255 
02256     remap.push_back(std::make_pair(I->first->getName(), TempFile));
02257   }
02258 
02259   return hasErrorOccurred;
02260 }