]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/llvm/tools/clang/lib/ARCMigrate/ObjCMT.cpp
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / llvm / tools / clang / lib / ARCMigrate / ObjCMT.cpp
1 //===--- ObjCMT.cpp - ObjC Migrate Tool -----------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "Transforms.h"
11 #include "clang/ARCMigrate/ARCMTActions.h"
12 #include "clang/AST/ASTConsumer.h"
13 #include "clang/AST/ASTContext.h"
14 #include "clang/AST/NSAPI.h"
15 #include "clang/AST/ParentMap.h"
16 #include "clang/AST/RecursiveASTVisitor.h"
17 #include "clang/Basic/FileManager.h"
18 #include "clang/Edit/Commit.h"
19 #include "clang/Edit/EditedSource.h"
20 #include "clang/Edit/EditsReceiver.h"
21 #include "clang/Edit/Rewriters.h"
22 #include "clang/Frontend/CompilerInstance.h"
23 #include "clang/Frontend/MultiplexConsumer.h"
24 #include "clang/Lex/PPConditionalDirectiveRecord.h"
25 #include "clang/Lex/Preprocessor.h"
26 #include "clang/Rewrite/Core/Rewriter.h"
27 #include "clang/Analysis/DomainSpecific/CocoaConventions.h"
28 #include "clang/StaticAnalyzer/Checkers/ObjCRetainCount.h"
29 #include "clang/AST/Attr.h"
30 #include "llvm/ADT/SmallString.h"
31 #include "llvm/Support/Path.h"
32
33 using namespace clang;
34 using namespace arcmt;
35 using namespace ento::objc_retain;
36
37 namespace {
38
39 class ObjCMigrateASTConsumer : public ASTConsumer {
40   enum CF_BRIDGING_KIND {
41     CF_BRIDGING_NONE,
42     CF_BRIDGING_ENABLE,
43     CF_BRIDGING_MAY_INCLUDE
44   };
45   
46   void migrateDecl(Decl *D);
47   void migrateObjCInterfaceDecl(ASTContext &Ctx, ObjCContainerDecl *D);
48   void migrateDeprecatedAnnotation(ASTContext &Ctx, ObjCCategoryDecl *CatDecl);
49   void migrateProtocolConformance(ASTContext &Ctx,
50                                   const ObjCImplementationDecl *ImpDecl);
51   void CacheObjCNSIntegerTypedefed(const TypedefDecl *TypedefDcl);
52   bool migrateNSEnumDecl(ASTContext &Ctx, const EnumDecl *EnumDcl,
53                      const TypedefDecl *TypedefDcl);
54   void migrateAllMethodInstaceType(ASTContext &Ctx, ObjCContainerDecl *CDecl);
55   void migrateMethodInstanceType(ASTContext &Ctx, ObjCContainerDecl *CDecl,
56                                  ObjCMethodDecl *OM);
57   bool migrateProperty(ASTContext &Ctx, ObjCContainerDecl *D, ObjCMethodDecl *OM);
58   void migrateNsReturnsInnerPointer(ASTContext &Ctx, ObjCMethodDecl *OM);
59   void migratePropertyNsReturnsInnerPointer(ASTContext &Ctx, ObjCPropertyDecl *P);
60   void migrateFactoryMethod(ASTContext &Ctx, ObjCContainerDecl *CDecl,
61                             ObjCMethodDecl *OM,
62                             ObjCInstanceTypeFamily OIT_Family = OIT_None);
63   
64   void migrateCFAnnotation(ASTContext &Ctx, const Decl *Decl);
65   void AddCFAnnotations(ASTContext &Ctx, const CallEffects &CE,
66                         const FunctionDecl *FuncDecl, bool ResultAnnotated);
67   void AddCFAnnotations(ASTContext &Ctx, const CallEffects &CE,
68                         const ObjCMethodDecl *MethodDecl, bool ResultAnnotated);
69   
70   void AnnotateImplicitBridging(ASTContext &Ctx);
71   
72   CF_BRIDGING_KIND migrateAddFunctionAnnotation(ASTContext &Ctx,
73                                                 const FunctionDecl *FuncDecl);
74   
75   void migrateARCSafeAnnotation(ASTContext &Ctx, ObjCContainerDecl *CDecl);
76   
77   void migrateAddMethodAnnotation(ASTContext &Ctx,
78                                   const ObjCMethodDecl *MethodDecl);
79 public:
80   std::string MigrateDir;
81   unsigned ASTMigrateActions;
82   FileID FileId;
83   const TypedefDecl *NSIntegerTypedefed;
84   const TypedefDecl *NSUIntegerTypedefed;
85   OwningPtr<NSAPI> NSAPIObj;
86   OwningPtr<edit::EditedSource> Editor;
87   FileRemapper &Remapper;
88   FileManager &FileMgr;
89   const PPConditionalDirectiveRecord *PPRec;
90   Preprocessor &PP;
91   bool IsOutputFile;
92   llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ObjCProtocolDecls;
93   llvm::SmallVector<const Decl *, 8> CFFunctionIBCandidates;
94   llvm::StringMap<char> WhiteListFilenames;
95   
96   ObjCMigrateASTConsumer(StringRef migrateDir,
97                          unsigned astMigrateActions,
98                          FileRemapper &remapper,
99                          FileManager &fileMgr,
100                          const PPConditionalDirectiveRecord *PPRec,
101                          Preprocessor &PP,
102                          bool isOutputFile,
103                          ArrayRef<std::string> WhiteList)
104   : MigrateDir(migrateDir),
105     ASTMigrateActions(astMigrateActions),
106     NSIntegerTypedefed(0), NSUIntegerTypedefed(0),
107     Remapper(remapper), FileMgr(fileMgr), PPRec(PPRec), PP(PP),
108     IsOutputFile(isOutputFile) {
109
110     for (ArrayRef<std::string>::iterator
111            I = WhiteList.begin(), E = WhiteList.end(); I != E; ++I) {
112       WhiteListFilenames.GetOrCreateValue(*I);
113     }
114   }
115
116 protected:
117   virtual void Initialize(ASTContext &Context) {
118     NSAPIObj.reset(new NSAPI(Context));
119     Editor.reset(new edit::EditedSource(Context.getSourceManager(),
120                                         Context.getLangOpts(),
121                                         PPRec, false));
122   }
123
124   virtual bool HandleTopLevelDecl(DeclGroupRef DG) {
125     for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
126       migrateDecl(*I);
127     return true;
128   }
129   virtual void HandleInterestingDecl(DeclGroupRef DG) {
130     // Ignore decls from the PCH.
131   }
132   virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) {
133     ObjCMigrateASTConsumer::HandleTopLevelDecl(DG);
134   }
135
136   virtual void HandleTranslationUnit(ASTContext &Ctx);
137
138   bool canModifyFile(StringRef Path) {
139     if (WhiteListFilenames.empty())
140       return true;
141     return WhiteListFilenames.find(llvm::sys::path::filename(Path))
142         != WhiteListFilenames.end();
143   }
144 };
145
146 }
147
148 ObjCMigrateAction::ObjCMigrateAction(FrontendAction *WrappedAction,
149                                      StringRef migrateDir,
150                                      unsigned migrateAction)
151   : WrapperFrontendAction(WrappedAction), MigrateDir(migrateDir),
152     ObjCMigAction(migrateAction),
153     CompInst(0) {
154   if (MigrateDir.empty())
155     MigrateDir = "."; // user current directory if none is given.
156 }
157
158 ASTConsumer *ObjCMigrateAction::CreateASTConsumer(CompilerInstance &CI,
159                                                   StringRef InFile) {
160   PPConditionalDirectiveRecord *
161     PPRec = new PPConditionalDirectiveRecord(CompInst->getSourceManager());
162   CompInst->getPreprocessor().addPPCallbacks(PPRec);
163   ASTConsumer *
164     WrappedConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile);
165   ASTConsumer *MTConsumer = new ObjCMigrateASTConsumer(MigrateDir,
166                                                        ObjCMigAction,
167                                                        Remapper,
168                                                     CompInst->getFileManager(),
169                                                        PPRec,
170                                                        CompInst->getPreprocessor(),
171                                                        false,
172                                                        ArrayRef<std::string>());
173   ASTConsumer *Consumers[] = { MTConsumer, WrappedConsumer };
174   return new MultiplexConsumer(Consumers);
175 }
176
177 bool ObjCMigrateAction::BeginInvocation(CompilerInstance &CI) {
178   Remapper.initFromDisk(MigrateDir, CI.getDiagnostics(),
179                         /*ignoreIfFilesChanges=*/true);
180   CompInst = &CI;
181   CI.getDiagnostics().setIgnoreAllWarnings(true);
182   return true;
183 }
184
185 namespace {
186 class ObjCMigrator : public RecursiveASTVisitor<ObjCMigrator> {
187   ObjCMigrateASTConsumer &Consumer;
188   ParentMap &PMap;
189
190 public:
191   ObjCMigrator(ObjCMigrateASTConsumer &consumer, ParentMap &PMap)
192     : Consumer(consumer), PMap(PMap) { }
193
194   bool shouldVisitTemplateInstantiations() const { return false; }
195   bool shouldWalkTypesOfTypeLocs() const { return false; }
196
197   bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
198     if (Consumer.ASTMigrateActions & FrontendOptions::ObjCMT_Literals) {
199       edit::Commit commit(*Consumer.Editor);
200       edit::rewriteToObjCLiteralSyntax(E, *Consumer.NSAPIObj, commit, &PMap);
201       Consumer.Editor->commit(commit);
202     }
203
204     if (Consumer.ASTMigrateActions & FrontendOptions::ObjCMT_Subscripting) {
205       edit::Commit commit(*Consumer.Editor);
206       edit::rewriteToObjCSubscriptSyntax(E, *Consumer.NSAPIObj, commit);
207       Consumer.Editor->commit(commit);
208     }
209
210     return true;
211   }
212
213   bool TraverseObjCMessageExpr(ObjCMessageExpr *E) {
214     // Do depth first; we want to rewrite the subexpressions first so that if
215     // we have to move expressions we will move them already rewritten.
216     for (Stmt::child_range range = E->children(); range; ++range)
217       if (!TraverseStmt(*range))
218         return false;
219
220     return WalkUpFromObjCMessageExpr(E);
221   }
222 };
223
224 class BodyMigrator : public RecursiveASTVisitor<BodyMigrator> {
225   ObjCMigrateASTConsumer &Consumer;
226   OwningPtr<ParentMap> PMap;
227
228 public:
229   BodyMigrator(ObjCMigrateASTConsumer &consumer) : Consumer(consumer) { }
230
231   bool shouldVisitTemplateInstantiations() const { return false; }
232   bool shouldWalkTypesOfTypeLocs() const { return false; }
233
234   bool TraverseStmt(Stmt *S) {
235     PMap.reset(new ParentMap(S));
236     ObjCMigrator(Consumer, *PMap).TraverseStmt(S);
237     return true;
238   }
239 };
240 }
241
242 void ObjCMigrateASTConsumer::migrateDecl(Decl *D) {
243   if (!D)
244     return;
245   if (isa<ObjCMethodDecl>(D))
246     return; // Wait for the ObjC container declaration.
247
248   BodyMigrator(*this).TraverseDecl(D);
249 }
250
251 static void append_attr(std::string &PropertyString, const char *attr,
252                         bool &LParenAdded) {
253   if (!LParenAdded) {
254     PropertyString += "(";
255     LParenAdded = true;
256   }
257   else
258     PropertyString += ", ";
259   PropertyString += attr;
260 }
261
262 static
263 void MigrateBlockOrFunctionPointerTypeVariable(std::string & PropertyString,
264                                                const std::string& TypeString,
265                                                const char *name) {
266   const char *argPtr = TypeString.c_str();
267   int paren = 0;
268   while (*argPtr) {
269     switch (*argPtr) {
270       case '(':
271         PropertyString += *argPtr;
272         paren++;
273         break;
274       case ')':
275         PropertyString += *argPtr;
276         paren--;
277         break;
278       case '^':
279       case '*':
280         PropertyString += (*argPtr);
281         if (paren == 1) {
282           PropertyString += name;
283           name = "";
284         }
285         break;
286       default:
287         PropertyString += *argPtr;
288         break;
289     }
290     argPtr++;
291   }
292 }
293
294 static const char *PropertyMemoryAttribute(ASTContext &Context, QualType ArgType) {
295   Qualifiers::ObjCLifetime propertyLifetime = ArgType.getObjCLifetime();
296   bool RetainableObject = ArgType->isObjCRetainableType();
297   if (RetainableObject && propertyLifetime == Qualifiers::OCL_Strong) {
298     if (const ObjCObjectPointerType *ObjPtrTy =
299         ArgType->getAs<ObjCObjectPointerType>()) {
300       ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface();
301       if (IDecl &&
302           IDecl->lookupNestedProtocol(&Context.Idents.get("NSCopying")))
303         return "copy";
304       else
305         return "retain";
306     }
307     else if (ArgType->isBlockPointerType())
308       return "copy";
309   } else if (propertyLifetime == Qualifiers::OCL_Weak)
310     // TODO. More precise determination of 'weak' attribute requires
311     // looking into setter's implementation for backing weak ivar.
312     return "weak";
313   else if (RetainableObject)
314     return ArgType->isBlockPointerType() ? "copy" : "retain";
315   return 0;
316 }
317
318 static void rewriteToObjCProperty(const ObjCMethodDecl *Getter,
319                                   const ObjCMethodDecl *Setter,
320                                   const NSAPI &NS, edit::Commit &commit,
321                                   unsigned LengthOfPrefix,
322                                   bool Atomic, bool UseNsIosOnlyMacro,
323                                   bool AvailabilityArgsMatch) {
324   ASTContext &Context = NS.getASTContext();
325   bool LParenAdded = false;
326   std::string PropertyString = "@property ";
327   if (UseNsIosOnlyMacro && Context.Idents.get("NS_NONATOMIC_IOSONLY").hasMacroDefinition()) {
328     PropertyString += "(NS_NONATOMIC_IOSONLY";
329     LParenAdded = true;
330   } else if (!Atomic) {
331     PropertyString += "(nonatomic";
332     LParenAdded = true;
333   }
334   
335   std::string PropertyNameString = Getter->getNameAsString();
336   StringRef PropertyName(PropertyNameString);
337   if (LengthOfPrefix > 0) {
338     if (!LParenAdded) {
339       PropertyString += "(getter=";
340       LParenAdded = true;
341     }
342     else
343       PropertyString += ", getter=";
344     PropertyString += PropertyNameString;
345   }
346   // Property with no setter may be suggested as a 'readonly' property.
347   if (!Setter) {
348     append_attr(PropertyString, "readonly", LParenAdded);
349     QualType ResType = Context.getCanonicalType(Getter->getResultType());
350     if (const char *MemoryManagementAttr = PropertyMemoryAttribute(Context, ResType))
351       append_attr(PropertyString, MemoryManagementAttr, LParenAdded);
352   }
353   
354   // Short circuit 'delegate' properties that contain the name "delegate" or
355   // "dataSource", or have exact name "target" to have 'assign' attribute.
356   if (PropertyName.equals("target") ||
357       (PropertyName.find("delegate") != StringRef::npos) ||
358       (PropertyName.find("dataSource") != StringRef::npos)) {
359     QualType QT = Getter->getResultType();
360     if (!QT->isRealType())
361       append_attr(PropertyString, "assign", LParenAdded);
362   }
363   else if (Setter) {
364     const ParmVarDecl *argDecl = *Setter->param_begin();
365     QualType ArgType = Context.getCanonicalType(argDecl->getType());
366     if (const char *MemoryManagementAttr = PropertyMemoryAttribute(Context, ArgType))
367       append_attr(PropertyString, MemoryManagementAttr, LParenAdded);
368   }
369   if (LParenAdded)
370     PropertyString += ')';
371   QualType RT = Getter->getResultType();
372   if (!isa<TypedefType>(RT)) {
373     // strip off any ARC lifetime qualifier.
374     QualType CanResultTy = Context.getCanonicalType(RT);
375     if (CanResultTy.getQualifiers().hasObjCLifetime()) {
376       Qualifiers Qs = CanResultTy.getQualifiers();
377       Qs.removeObjCLifetime();
378       RT = Context.getQualifiedType(CanResultTy.getUnqualifiedType(), Qs);
379     }
380   }
381   PropertyString += " ";
382   PrintingPolicy SubPolicy(Context.getPrintingPolicy());
383   SubPolicy.SuppressStrongLifetime = true;
384   SubPolicy.SuppressLifetimeQualifiers = true;
385   std::string TypeString = RT.getAsString(SubPolicy);
386   if (LengthOfPrefix > 0) {
387     // property name must strip off "is" and lower case the first character
388     // after that; e.g. isContinuous will become continuous.
389     StringRef PropertyNameStringRef(PropertyNameString);
390     PropertyNameStringRef = PropertyNameStringRef.drop_front(LengthOfPrefix);
391     PropertyNameString = PropertyNameStringRef;
392     bool NoLowering = (isUppercase(PropertyNameString[0]) &&
393                        PropertyNameString.size() > 1 &&
394                        isUppercase(PropertyNameString[1]));
395     if (!NoLowering)
396       PropertyNameString[0] = toLowercase(PropertyNameString[0]);
397   }
398   if (RT->isBlockPointerType() || RT->isFunctionPointerType())
399     MigrateBlockOrFunctionPointerTypeVariable(PropertyString,
400                                               TypeString,
401                                               PropertyNameString.c_str());
402   else {
403     char LastChar = TypeString[TypeString.size()-1];
404     PropertyString += TypeString;
405     if (LastChar != '*')
406       PropertyString += ' ';
407     PropertyString += PropertyNameString;
408   }
409   SourceLocation StartGetterSelectorLoc = Getter->getSelectorStartLoc();
410   Selector GetterSelector = Getter->getSelector();
411   
412   SourceLocation EndGetterSelectorLoc =
413     StartGetterSelectorLoc.getLocWithOffset(GetterSelector.getNameForSlot(0).size());
414   commit.replace(CharSourceRange::getCharRange(Getter->getLocStart(),
415                                                EndGetterSelectorLoc),
416                  PropertyString);
417   if (Setter && AvailabilityArgsMatch) {
418     SourceLocation EndLoc = Setter->getDeclaratorEndLoc();
419     // Get location past ';'
420     EndLoc = EndLoc.getLocWithOffset(1);
421     SourceLocation BeginOfSetterDclLoc = Setter->getLocStart();
422     // FIXME. This assumes that setter decl; is immediately preceeded by eoln.
423     // It is trying to remove the setter method decl. line entirely.
424     BeginOfSetterDclLoc = BeginOfSetterDclLoc.getLocWithOffset(-1);
425     commit.remove(SourceRange(BeginOfSetterDclLoc, EndLoc));
426   }
427 }
428
429 void ObjCMigrateASTConsumer::migrateObjCInterfaceDecl(ASTContext &Ctx,
430                                                       ObjCContainerDecl *D) {
431   if (D->isDeprecated())
432     return;
433   
434   for (ObjCContainerDecl::method_iterator M = D->meth_begin(), MEnd = D->meth_end();
435        M != MEnd; ++M) {
436     ObjCMethodDecl *Method = (*M);
437     if (Method->isDeprecated())
438       continue;
439     bool PropertyInferred = migrateProperty(Ctx, D, Method);
440     // If a property is inferred, do not attempt to attach NS_RETURNS_INNER_POINTER to
441     // the getter method as it ends up on the property itself which we don't want
442     // to do unless -objcmt-returns-innerpointer-property  option is on.
443     if (!PropertyInferred ||
444         (ASTMigrateActions & FrontendOptions::ObjCMT_ReturnsInnerPointerProperty))
445       if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation)
446         migrateNsReturnsInnerPointer(Ctx, Method);
447   }
448   if (!(ASTMigrateActions & FrontendOptions::ObjCMT_ReturnsInnerPointerProperty))
449     return;
450   
451   for (ObjCContainerDecl::prop_iterator P = D->prop_begin(),
452        E = D->prop_end(); P != E; ++P) {
453     ObjCPropertyDecl *Prop = *P;
454     if ((ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) &&
455         !Prop->isDeprecated())
456       migratePropertyNsReturnsInnerPointer(Ctx, Prop);
457   }
458 }
459
460 void ObjCMigrateASTConsumer::migrateDeprecatedAnnotation(ASTContext &Ctx,
461                                                            ObjCCategoryDecl *CatDecl) {
462   StringRef Name = CatDecl->getName();
463   if (!Name.endswith("Deprecated"))
464     return;
465   
466   if (!Ctx.Idents.get("DEPRECATED").hasMacroDefinition())
467     return;
468   
469   ObjCContainerDecl *D = cast<ObjCContainerDecl>(CatDecl);
470   
471   for (ObjCContainerDecl::method_iterator M = D->meth_begin(), MEnd = D->meth_end();
472        M != MEnd; ++M) {
473     ObjCMethodDecl *Method = (*M);
474     if (Method->isDeprecated() || Method->isImplicit())
475       continue;
476     // Annotate with DEPRECATED
477     edit::Commit commit(*Editor);
478     commit.insertBefore(Method->getLocEnd(), " DEPRECATED");
479     Editor->commit(commit);
480   }
481   for (ObjCContainerDecl::prop_iterator P = D->prop_begin(),
482        E = D->prop_end(); P != E; ++P) {
483     ObjCPropertyDecl *Prop = *P;
484     if (Prop->isDeprecated())
485       continue;
486     // Annotate with DEPRECATED
487     edit::Commit commit(*Editor);
488     commit.insertAfterToken(Prop->getLocEnd(), " DEPRECATED");
489     Editor->commit(commit);
490   }
491 }
492
493 static bool
494 ClassImplementsAllMethodsAndProperties(ASTContext &Ctx,
495                                       const ObjCImplementationDecl *ImpDecl,
496                                        const ObjCInterfaceDecl *IDecl,
497                                       ObjCProtocolDecl *Protocol) {
498   // In auto-synthesis, protocol properties are not synthesized. So,
499   // a conforming protocol must have its required properties declared
500   // in class interface.
501   bool HasAtleastOneRequiredProperty = false;
502   if (const ObjCProtocolDecl *PDecl = Protocol->getDefinition())
503     for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
504          E = PDecl->prop_end(); P != E; ++P) {
505       ObjCPropertyDecl *Property = *P;
506       if (Property->getPropertyImplementation() == ObjCPropertyDecl::Optional)
507         continue;
508       HasAtleastOneRequiredProperty = true;
509       DeclContext::lookup_const_result R = IDecl->lookup(Property->getDeclName());
510       if (R.size() == 0) {
511         // Relax the rule and look into class's implementation for a synthesize
512         // or dynamic declaration. Class is implementing a property coming from
513         // another protocol. This still makes the target protocol as conforming.
514         if (!ImpDecl->FindPropertyImplDecl(
515                                   Property->getDeclName().getAsIdentifierInfo()))
516           return false;
517       }
518       else if (ObjCPropertyDecl *ClassProperty = dyn_cast<ObjCPropertyDecl>(R[0])) {
519           if ((ClassProperty->getPropertyAttributes()
520               != Property->getPropertyAttributes()) ||
521               !Ctx.hasSameType(ClassProperty->getType(), Property->getType()))
522             return false;
523       }
524       else
525         return false;
526     }
527   
528   // At this point, all required properties in this protocol conform to those
529   // declared in the class.
530   // Check that class implements the required methods of the protocol too.
531   bool HasAtleastOneRequiredMethod = false;
532   if (const ObjCProtocolDecl *PDecl = Protocol->getDefinition()) {
533     if (PDecl->meth_begin() == PDecl->meth_end())
534       return HasAtleastOneRequiredProperty;
535     for (ObjCContainerDecl::method_iterator M = PDecl->meth_begin(),
536          MEnd = PDecl->meth_end(); M != MEnd; ++M) {
537       ObjCMethodDecl *MD = (*M);
538       if (MD->isImplicit())
539         continue;
540       if (MD->getImplementationControl() == ObjCMethodDecl::Optional)
541         continue;
542       DeclContext::lookup_const_result R = ImpDecl->lookup(MD->getDeclName());
543       if (R.size() == 0)
544         return false;
545       bool match = false;
546       HasAtleastOneRequiredMethod = true;
547       for (unsigned I = 0, N = R.size(); I != N; ++I)
548         if (ObjCMethodDecl *ImpMD = dyn_cast<ObjCMethodDecl>(R[0]))
549           if (Ctx.ObjCMethodsAreEqual(MD, ImpMD)) {
550             match = true;
551             break;
552           }
553       if (!match)
554         return false;
555     }
556   }
557   if (HasAtleastOneRequiredProperty || HasAtleastOneRequiredMethod)
558     return true;
559   return false;
560 }
561
562 static bool rewriteToObjCInterfaceDecl(const ObjCInterfaceDecl *IDecl,
563                     llvm::SmallVectorImpl<ObjCProtocolDecl*> &ConformingProtocols,
564                     const NSAPI &NS, edit::Commit &commit) {
565   const ObjCList<ObjCProtocolDecl> &Protocols = IDecl->getReferencedProtocols();
566   std::string ClassString;
567   SourceLocation EndLoc =
568   IDecl->getSuperClass() ? IDecl->getSuperClassLoc() : IDecl->getLocation();
569   
570   if (Protocols.empty()) {
571     ClassString = '<';
572     for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
573       ClassString += ConformingProtocols[i]->getNameAsString();
574       if (i != (e-1))
575         ClassString += ", ";
576     }
577     ClassString += "> ";
578   }
579   else {
580     ClassString = ", ";
581     for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
582       ClassString += ConformingProtocols[i]->getNameAsString();
583       if (i != (e-1))
584         ClassString += ", ";
585     }
586     ObjCInterfaceDecl::protocol_loc_iterator PL = IDecl->protocol_loc_end() - 1;
587     EndLoc = *PL;
588   }
589   
590   commit.insertAfterToken(EndLoc, ClassString);
591   return true;
592 }
593
594 static bool rewriteToNSEnumDecl(const EnumDecl *EnumDcl,
595                                 const TypedefDecl *TypedefDcl,
596                                 const NSAPI &NS, edit::Commit &commit,
597                                 bool IsNSIntegerType,
598                                 bool NSOptions) {
599   std::string ClassString;
600   if (NSOptions)
601     ClassString = "typedef NS_OPTIONS(NSUInteger, ";
602   else
603     ClassString =
604       IsNSIntegerType ? "typedef NS_ENUM(NSInteger, "
605                       : "typedef NS_ENUM(NSUInteger, ";
606   
607   ClassString += TypedefDcl->getIdentifier()->getName();
608   ClassString += ')';
609   SourceRange R(EnumDcl->getLocStart(), EnumDcl->getLocStart());
610   commit.replace(R, ClassString);
611   SourceLocation EndOfEnumDclLoc = EnumDcl->getLocEnd();
612   EndOfEnumDclLoc = trans::findSemiAfterLocation(EndOfEnumDclLoc,
613                                                  NS.getASTContext(), /*IsDecl*/true);
614   if (!EndOfEnumDclLoc.isInvalid()) {
615     SourceRange EnumDclRange(EnumDcl->getLocStart(), EndOfEnumDclLoc);
616     commit.insertFromRange(TypedefDcl->getLocStart(), EnumDclRange);
617   }
618   else
619     return false;
620   
621   SourceLocation EndTypedefDclLoc = TypedefDcl->getLocEnd();
622   EndTypedefDclLoc = trans::findSemiAfterLocation(EndTypedefDclLoc,
623                                                  NS.getASTContext(), /*IsDecl*/true);
624   if (!EndTypedefDclLoc.isInvalid()) {
625     SourceRange TDRange(TypedefDcl->getLocStart(), EndTypedefDclLoc);
626     commit.remove(TDRange);
627   }
628   else
629     return false;
630
631   EndOfEnumDclLoc = trans::findLocationAfterSemi(EnumDcl->getLocEnd(), NS.getASTContext(),
632                                                  /*IsDecl*/true);
633   if (!EndOfEnumDclLoc.isInvalid()) {
634     SourceLocation BeginOfEnumDclLoc = EnumDcl->getLocStart();
635     // FIXME. This assumes that enum decl; is immediately preceeded by eoln.
636     // It is trying to remove the enum decl. lines entirely.
637     BeginOfEnumDclLoc = BeginOfEnumDclLoc.getLocWithOffset(-1);
638     commit.remove(SourceRange(BeginOfEnumDclLoc, EndOfEnumDclLoc));
639     return true;
640   }
641   return false;
642 }
643
644 static void rewriteToNSMacroDecl(const EnumDecl *EnumDcl,
645                                 const TypedefDecl *TypedefDcl,
646                                 const NSAPI &NS, edit::Commit &commit,
647                                  bool IsNSIntegerType) {
648   std::string ClassString =
649     IsNSIntegerType ? "NS_ENUM(NSInteger, " : "NS_OPTIONS(NSUInteger, ";
650   ClassString += TypedefDcl->getIdentifier()->getName();
651   ClassString += ')';
652   SourceRange R(EnumDcl->getLocStart(), EnumDcl->getLocStart());
653   commit.replace(R, ClassString);
654   SourceLocation TypedefLoc = TypedefDcl->getLocEnd();
655   commit.remove(SourceRange(TypedefLoc, TypedefLoc));
656 }
657
658 static bool UseNSOptionsMacro(Preprocessor &PP, ASTContext &Ctx,
659                               const EnumDecl *EnumDcl) {
660   bool PowerOfTwo = true;
661   bool AllHexdecimalEnumerator = true;
662   uint64_t MaxPowerOfTwoVal = 0;
663   for (EnumDecl::enumerator_iterator EI = EnumDcl->enumerator_begin(),
664        EE = EnumDcl->enumerator_end(); EI != EE; ++EI) {
665     EnumConstantDecl *Enumerator = (*EI);
666     const Expr *InitExpr = Enumerator->getInitExpr();
667     if (!InitExpr) {
668       PowerOfTwo = false;
669       AllHexdecimalEnumerator = false;
670       continue;
671     }
672     InitExpr = InitExpr->IgnoreParenCasts();
673     if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(InitExpr))
674       if (BO->isShiftOp() || BO->isBitwiseOp())
675         return true;
676     
677     uint64_t EnumVal = Enumerator->getInitVal().getZExtValue();
678     if (PowerOfTwo && EnumVal) {
679       if (!llvm::isPowerOf2_64(EnumVal))
680         PowerOfTwo = false;
681       else if (EnumVal > MaxPowerOfTwoVal)
682         MaxPowerOfTwoVal = EnumVal;
683     }
684     if (AllHexdecimalEnumerator && EnumVal) {
685       bool FoundHexdecimalEnumerator = false;
686       SourceLocation EndLoc = Enumerator->getLocEnd();
687       Token Tok;
688       if (!PP.getRawToken(EndLoc, Tok, /*IgnoreWhiteSpace=*/true))
689         if (Tok.isLiteral() && Tok.getLength() > 2) {
690           if (const char *StringLit = Tok.getLiteralData())
691             FoundHexdecimalEnumerator =
692               (StringLit[0] == '0' && (toLowercase(StringLit[1]) == 'x'));
693         }
694       if (!FoundHexdecimalEnumerator)
695         AllHexdecimalEnumerator = false;
696     }
697   }
698   return AllHexdecimalEnumerator || (PowerOfTwo && (MaxPowerOfTwoVal > 2));
699 }
700
701 void ObjCMigrateASTConsumer::migrateProtocolConformance(ASTContext &Ctx,   
702                                             const ObjCImplementationDecl *ImpDecl) {
703   const ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface();
704   if (!IDecl || ObjCProtocolDecls.empty() || IDecl->isDeprecated())
705     return;
706   // Find all implicit conforming protocols for this class
707   // and make them explicit.
708   llvm::SmallPtrSet<ObjCProtocolDecl *, 8> ExplicitProtocols;
709   Ctx.CollectInheritedProtocols(IDecl, ExplicitProtocols);
710   llvm::SmallVector<ObjCProtocolDecl *, 8> PotentialImplicitProtocols;
711   
712   for (llvm::SmallPtrSet<ObjCProtocolDecl*, 32>::iterator I =
713        ObjCProtocolDecls.begin(),
714        E = ObjCProtocolDecls.end(); I != E; ++I)
715     if (!ExplicitProtocols.count(*I))
716       PotentialImplicitProtocols.push_back(*I);
717   
718   if (PotentialImplicitProtocols.empty())
719     return;
720
721   // go through list of non-optional methods and properties in each protocol
722   // in the PotentialImplicitProtocols list. If class implements every one of the
723   // methods and properties, then this class conforms to this protocol.
724   llvm::SmallVector<ObjCProtocolDecl*, 8> ConformingProtocols;
725   for (unsigned i = 0, e = PotentialImplicitProtocols.size(); i != e; i++)
726     if (ClassImplementsAllMethodsAndProperties(Ctx, ImpDecl, IDecl,
727                                               PotentialImplicitProtocols[i]))
728       ConformingProtocols.push_back(PotentialImplicitProtocols[i]);
729   
730   if (ConformingProtocols.empty())
731     return;
732   
733   // Further reduce number of conforming protocols. If protocol P1 is in the list
734   // protocol P2 (P2<P1>), No need to include P1.
735   llvm::SmallVector<ObjCProtocolDecl*, 8> MinimalConformingProtocols;
736   for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
737     bool DropIt = false;
738     ObjCProtocolDecl *TargetPDecl = ConformingProtocols[i];
739     for (unsigned i1 = 0, e1 = ConformingProtocols.size(); i1 != e1; i1++) {
740       ObjCProtocolDecl *PDecl = ConformingProtocols[i1];
741       if (PDecl == TargetPDecl)
742         continue;
743       if (PDecl->lookupProtocolNamed(
744             TargetPDecl->getDeclName().getAsIdentifierInfo())) {
745         DropIt = true;
746         break;
747       }
748     }
749     if (!DropIt)
750       MinimalConformingProtocols.push_back(TargetPDecl);
751   }
752   edit::Commit commit(*Editor);
753   rewriteToObjCInterfaceDecl(IDecl, MinimalConformingProtocols,
754                              *NSAPIObj, commit);
755   Editor->commit(commit);
756 }
757
758 void ObjCMigrateASTConsumer::CacheObjCNSIntegerTypedefed(
759                                           const TypedefDecl *TypedefDcl) {
760   
761   QualType qt = TypedefDcl->getTypeSourceInfo()->getType();
762   if (NSAPIObj->isObjCNSIntegerType(qt))
763     NSIntegerTypedefed = TypedefDcl;
764   else if (NSAPIObj->isObjCNSUIntegerType(qt))
765     NSUIntegerTypedefed = TypedefDcl;
766 }
767
768 bool ObjCMigrateASTConsumer::migrateNSEnumDecl(ASTContext &Ctx,
769                                            const EnumDecl *EnumDcl,
770                                            const TypedefDecl *TypedefDcl) {
771   if (!EnumDcl->isCompleteDefinition() || EnumDcl->getIdentifier() ||
772       EnumDcl->isDeprecated())
773     return false;
774   if (!TypedefDcl) {
775     if (NSIntegerTypedefed) {
776       TypedefDcl = NSIntegerTypedefed;
777       NSIntegerTypedefed = 0;
778     }
779     else if (NSUIntegerTypedefed) {
780       TypedefDcl = NSUIntegerTypedefed;
781       NSUIntegerTypedefed = 0;
782     }
783     else
784       return false;
785     FileID FileIdOfTypedefDcl =
786       PP.getSourceManager().getFileID(TypedefDcl->getLocation());
787     FileID FileIdOfEnumDcl =
788       PP.getSourceManager().getFileID(EnumDcl->getLocation());
789     if (FileIdOfTypedefDcl != FileIdOfEnumDcl)
790       return false;
791   }
792   if (TypedefDcl->isDeprecated())
793     return false;
794   
795   QualType qt = TypedefDcl->getTypeSourceInfo()->getType();
796   bool IsNSIntegerType = NSAPIObj->isObjCNSIntegerType(qt);
797   bool IsNSUIntegerType = !IsNSIntegerType && NSAPIObj->isObjCNSUIntegerType(qt);
798   
799   if (!IsNSIntegerType && !IsNSUIntegerType) {
800     // Also check for typedef enum {...} TD;
801     if (const EnumType *EnumTy = qt->getAs<EnumType>()) {
802       if (EnumTy->getDecl() == EnumDcl) {
803         bool NSOptions = UseNSOptionsMacro(PP, Ctx, EnumDcl);
804         if (NSOptions) {
805           if (!Ctx.Idents.get("NS_OPTIONS").hasMacroDefinition())
806             return false;
807         }
808         else if (!Ctx.Idents.get("NS_ENUM").hasMacroDefinition())
809           return false;
810         edit::Commit commit(*Editor);
811         rewriteToNSMacroDecl(EnumDcl, TypedefDcl, *NSAPIObj, commit, !NSOptions);
812         Editor->commit(commit);
813         return true;
814       }
815     }
816     return false;
817   }
818   
819   // We may still use NS_OPTIONS based on what we find in the enumertor list.
820   bool NSOptions = UseNSOptionsMacro(PP, Ctx, EnumDcl);
821   // NS_ENUM must be available.
822   if (IsNSIntegerType && !Ctx.Idents.get("NS_ENUM").hasMacroDefinition())
823     return false;
824   // NS_OPTIONS must be available.
825   if (IsNSUIntegerType && !Ctx.Idents.get("NS_OPTIONS").hasMacroDefinition())
826     return false;
827   edit::Commit commit(*Editor);
828   bool Res = rewriteToNSEnumDecl(EnumDcl, TypedefDcl, *NSAPIObj,
829                                  commit, IsNSIntegerType, NSOptions);
830   Editor->commit(commit);
831   return Res;
832 }
833
834 static void ReplaceWithInstancetype(const ObjCMigrateASTConsumer &ASTC,
835                                     ObjCMethodDecl *OM) {
836   SourceRange R;
837   std::string ClassString;
838   if (TypeSourceInfo *TSInfo =  OM->getResultTypeSourceInfo()) {
839     TypeLoc TL = TSInfo->getTypeLoc();
840     R = SourceRange(TL.getBeginLoc(), TL.getEndLoc());
841     ClassString = "instancetype";
842   }
843   else {
844     R = SourceRange(OM->getLocStart(), OM->getLocStart());
845     ClassString = OM->isInstanceMethod() ? '-' : '+';
846     ClassString += " (instancetype)";
847   }
848   edit::Commit commit(*ASTC.Editor);
849   commit.replace(R, ClassString);
850   ASTC.Editor->commit(commit);
851 }
852
853 static void ReplaceWithClasstype(const ObjCMigrateASTConsumer &ASTC,
854                                     ObjCMethodDecl *OM) {
855   ObjCInterfaceDecl *IDecl = OM->getClassInterface();
856   SourceRange R;
857   std::string ClassString;
858   if (TypeSourceInfo *TSInfo =  OM->getResultTypeSourceInfo()) {
859     TypeLoc TL = TSInfo->getTypeLoc();
860     R = SourceRange(TL.getBeginLoc(), TL.getEndLoc()); {
861       ClassString  = IDecl->getName();
862       ClassString += "*";
863     }
864   }
865   else {
866     R = SourceRange(OM->getLocStart(), OM->getLocStart());
867     ClassString = "+ (";
868     ClassString += IDecl->getName(); ClassString += "*)";
869   }
870   edit::Commit commit(*ASTC.Editor);
871   commit.replace(R, ClassString);
872   ASTC.Editor->commit(commit);
873 }
874
875 void ObjCMigrateASTConsumer::migrateMethodInstanceType(ASTContext &Ctx,
876                                                        ObjCContainerDecl *CDecl,
877                                                        ObjCMethodDecl *OM) {
878   ObjCInstanceTypeFamily OIT_Family =
879     Selector::getInstTypeMethodFamily(OM->getSelector());
880   
881   std::string ClassName;
882   switch (OIT_Family) {
883     case OIT_None:
884       migrateFactoryMethod(Ctx, CDecl, OM);
885       return;
886     case OIT_Array:
887       ClassName = "NSArray";
888       break;
889     case OIT_Dictionary:
890       ClassName = "NSDictionary";
891       break;
892     case OIT_Singleton:
893       migrateFactoryMethod(Ctx, CDecl, OM, OIT_Singleton);
894       return;
895     case OIT_Init:
896       if (OM->getResultType()->isObjCIdType())
897         ReplaceWithInstancetype(*this, OM);
898       return;
899     case OIT_ReturnsSelf:
900       migrateFactoryMethod(Ctx, CDecl, OM, OIT_ReturnsSelf);
901       return;
902   }
903   if (!OM->getResultType()->isObjCIdType())
904     return;
905   
906   ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl);
907   if (!IDecl) {
908     if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl))
909       IDecl = CatDecl->getClassInterface();
910     else if (ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(CDecl))
911       IDecl = ImpDecl->getClassInterface();
912   }
913   if (!IDecl ||
914       !IDecl->lookupInheritedClass(&Ctx.Idents.get(ClassName))) {
915     migrateFactoryMethod(Ctx, CDecl, OM);
916     return;
917   }
918   ReplaceWithInstancetype(*this, OM);
919 }
920
921 static bool TypeIsInnerPointer(QualType T) {
922   if (!T->isAnyPointerType())
923     return false;
924   if (T->isObjCObjectPointerType() || T->isObjCBuiltinType() ||
925       T->isBlockPointerType() || T->isFunctionPointerType() ||
926       ento::coreFoundation::isCFObjectRef(T))
927     return false;
928   // Also, typedef-of-pointer-to-incomplete-struct is something that we assume
929   // is not an innter pointer type.
930   QualType OrigT = T;
931   while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr()))
932     T = TD->getDecl()->getUnderlyingType();
933   if (OrigT == T || !T->isPointerType())
934     return true;
935   const PointerType* PT = T->getAs<PointerType>();
936   QualType UPointeeT = PT->getPointeeType().getUnqualifiedType();
937   if (UPointeeT->isRecordType()) {
938     const RecordType *RecordTy = UPointeeT->getAs<RecordType>();
939     if (!RecordTy->getDecl()->isCompleteDefinition())
940       return false;
941   }
942   return true;
943 }
944
945 /// \brief Check whether the two versions match.
946 static bool versionsMatch(const VersionTuple &X, const VersionTuple &Y) {
947   return (X == Y);
948 }
949
950 /// AvailabilityAttrsMatch - This routine checks that if comparing two
951 /// availability attributes, all their components match. It returns
952 /// true, if not dealing with availability or when all components of
953 /// availability attributes match. This routine is only called when
954 /// the attributes are of the same kind.
955 static bool AvailabilityAttrsMatch(Attr *At1, Attr *At2) {
956   const AvailabilityAttr *AA1 = dyn_cast<AvailabilityAttr>(At1);
957   if (!AA1)
958     return true;
959   const AvailabilityAttr *AA2 = dyn_cast<AvailabilityAttr>(At2);
960   
961   VersionTuple Introduced1 = AA1->getIntroduced();
962   VersionTuple Deprecated1 = AA1->getDeprecated();
963   VersionTuple Obsoleted1 = AA1->getObsoleted();
964   bool IsUnavailable1 = AA1->getUnavailable();
965   VersionTuple Introduced2 = AA2->getIntroduced();
966   VersionTuple Deprecated2 = AA2->getDeprecated();
967   VersionTuple Obsoleted2 = AA2->getObsoleted();
968   bool IsUnavailable2 = AA2->getUnavailable();
969   return (versionsMatch(Introduced1, Introduced2) &&
970           versionsMatch(Deprecated1, Deprecated2) &&
971           versionsMatch(Obsoleted1, Obsoleted2) &&
972           IsUnavailable1 == IsUnavailable2);
973   
974 }
975
976 static bool MatchTwoAttributeLists(const AttrVec &Attrs1, const AttrVec &Attrs2,
977                                    bool &AvailabilityArgsMatch) {
978   // This list is very small, so this need not be optimized.
979   for (unsigned i = 0, e = Attrs1.size(); i != e; i++) {
980     bool match = false;
981     for (unsigned j = 0, f = Attrs2.size(); j != f; j++) {
982       // Matching attribute kind only. Except for Availabilty attributes,
983       // we are not getting into details of the attributes. For all practical purposes
984       // this is sufficient.
985       if (Attrs1[i]->getKind() == Attrs2[j]->getKind()) {
986         if (AvailabilityArgsMatch)
987           AvailabilityArgsMatch = AvailabilityAttrsMatch(Attrs1[i], Attrs2[j]);
988         match = true;
989         break;
990       }
991     }
992     if (!match)
993       return false;
994   }
995   return true;
996 }
997
998 /// AttributesMatch - This routine checks list of attributes for two
999 /// decls. It returns false, if there is a mismatch in kind of
1000 /// attributes seen in the decls. It returns true if the two decls
1001 /// have list of same kind of attributes. Furthermore, when there
1002 /// are availability attributes in the two decls, it sets the
1003 /// AvailabilityArgsMatch to false if availability attributes have
1004 /// different versions, etc.
1005 static bool AttributesMatch(const Decl *Decl1, const Decl *Decl2,
1006                             bool &AvailabilityArgsMatch) {
1007   if (!Decl1->hasAttrs() || !Decl2->hasAttrs()) {
1008     AvailabilityArgsMatch = (Decl1->hasAttrs() == Decl2->hasAttrs());
1009     return true;
1010   }
1011   AvailabilityArgsMatch = true;
1012   const AttrVec &Attrs1 = Decl1->getAttrs();
1013   const AttrVec &Attrs2 = Decl2->getAttrs();
1014   bool match = MatchTwoAttributeLists(Attrs1, Attrs2, AvailabilityArgsMatch);
1015   if (match && (Attrs2.size() > Attrs1.size()))
1016     return MatchTwoAttributeLists(Attrs2, Attrs1, AvailabilityArgsMatch);
1017   return match;
1018 }
1019
1020 static bool IsValidIdentifier(ASTContext &Ctx,
1021                               const char *Name) {
1022   if (!isIdentifierHead(Name[0]))
1023     return false;
1024   std::string NameString = Name;
1025   NameString[0] = toLowercase(NameString[0]);
1026   IdentifierInfo *II = &Ctx.Idents.get(NameString);
1027   return II->getTokenID() ==  tok::identifier;
1028 }
1029
1030 bool ObjCMigrateASTConsumer::migrateProperty(ASTContext &Ctx,
1031                              ObjCContainerDecl *D,
1032                              ObjCMethodDecl *Method) {
1033   if (Method->isPropertyAccessor() || !Method->isInstanceMethod() ||
1034       Method->param_size() != 0)
1035     return false;
1036   // Is this method candidate to be a getter?
1037   QualType GRT = Method->getResultType();
1038   if (GRT->isVoidType())
1039     return false;
1040   
1041   Selector GetterSelector = Method->getSelector();
1042   ObjCInstanceTypeFamily OIT_Family =
1043     Selector::getInstTypeMethodFamily(GetterSelector);
1044   
1045   if (OIT_Family != OIT_None)
1046     return false;
1047   
1048   IdentifierInfo *getterName = GetterSelector.getIdentifierInfoForSlot(0);
1049   Selector SetterSelector =
1050   SelectorTable::constructSetterSelector(PP.getIdentifierTable(),
1051                                          PP.getSelectorTable(),
1052                                          getterName);
1053   ObjCMethodDecl *SetterMethod = D->getInstanceMethod(SetterSelector);
1054   unsigned LengthOfPrefix = 0;
1055   if (!SetterMethod) {
1056     // try a different naming convention for getter: isXxxxx
1057     StringRef getterNameString = getterName->getName();
1058     bool IsPrefix = getterNameString.startswith("is");
1059     // Note that we don't want to change an isXXX method of retainable object
1060     // type to property (readonly or otherwise).
1061     if (IsPrefix && GRT->isObjCRetainableType())
1062       return false;
1063     if (IsPrefix || getterNameString.startswith("get")) {
1064       LengthOfPrefix = (IsPrefix ? 2 : 3);
1065       const char *CGetterName = getterNameString.data() + LengthOfPrefix;
1066       // Make sure that first character after "is" or "get" prefix can
1067       // start an identifier.
1068       if (!IsValidIdentifier(Ctx, CGetterName))
1069         return false;
1070       if (CGetterName[0] && isUppercase(CGetterName[0])) {
1071         getterName = &Ctx.Idents.get(CGetterName);
1072         SetterSelector =
1073         SelectorTable::constructSetterSelector(PP.getIdentifierTable(),
1074                                                PP.getSelectorTable(),
1075                                                getterName);
1076         SetterMethod = D->getInstanceMethod(SetterSelector);
1077       }
1078     }
1079   }
1080   
1081   if (SetterMethod) {
1082     if ((ASTMigrateActions & FrontendOptions::ObjCMT_ReadwriteProperty) == 0)
1083       return false;
1084     bool AvailabilityArgsMatch;
1085     if (SetterMethod->isDeprecated() ||
1086         !AttributesMatch(Method, SetterMethod, AvailabilityArgsMatch))
1087       return false;
1088     
1089     // Is this a valid setter, matching the target getter?
1090     QualType SRT = SetterMethod->getResultType();
1091     if (!SRT->isVoidType())
1092       return false;
1093     const ParmVarDecl *argDecl = *SetterMethod->param_begin();
1094     QualType ArgType = argDecl->getType();
1095     if (!Ctx.hasSameUnqualifiedType(ArgType, GRT))
1096       return false;
1097     edit::Commit commit(*Editor);
1098     rewriteToObjCProperty(Method, SetterMethod, *NSAPIObj, commit,
1099                           LengthOfPrefix,
1100                           (ASTMigrateActions &
1101                            FrontendOptions::ObjCMT_AtomicProperty) != 0,
1102                           (ASTMigrateActions &
1103                            FrontendOptions::ObjCMT_NsAtomicIOSOnlyProperty) != 0,
1104                           AvailabilityArgsMatch);
1105     Editor->commit(commit);
1106     return true;
1107   }
1108   else if (ASTMigrateActions & FrontendOptions::ObjCMT_ReadonlyProperty) {
1109     // Try a non-void method with no argument (and no setter or property of same name
1110     // as a 'readonly' property.
1111     edit::Commit commit(*Editor);
1112     rewriteToObjCProperty(Method, 0 /*SetterMethod*/, *NSAPIObj, commit,
1113                           LengthOfPrefix,
1114                           (ASTMigrateActions &
1115                            FrontendOptions::ObjCMT_AtomicProperty) != 0,
1116                           (ASTMigrateActions &
1117                            FrontendOptions::ObjCMT_NsAtomicIOSOnlyProperty) != 0,
1118                           /*AvailabilityArgsMatch*/false);
1119     Editor->commit(commit);
1120     return true;
1121   }
1122   return false;
1123 }
1124
1125 void ObjCMigrateASTConsumer::migrateNsReturnsInnerPointer(ASTContext &Ctx,
1126                                                           ObjCMethodDecl *OM) {
1127   if (OM->isImplicit() ||
1128       !OM->isInstanceMethod() ||
1129       OM->hasAttr<ObjCReturnsInnerPointerAttr>())
1130     return;
1131   
1132   QualType RT = OM->getResultType();
1133   if (!TypeIsInnerPointer(RT) ||
1134       !Ctx.Idents.get("NS_RETURNS_INNER_POINTER").hasMacroDefinition())
1135     return;
1136   
1137   edit::Commit commit(*Editor);
1138   commit.insertBefore(OM->getLocEnd(), " NS_RETURNS_INNER_POINTER");
1139   Editor->commit(commit);
1140 }
1141
1142 void ObjCMigrateASTConsumer::migratePropertyNsReturnsInnerPointer(ASTContext &Ctx,
1143                                                                   ObjCPropertyDecl *P) {
1144   QualType T = P->getType();
1145   
1146   if (!TypeIsInnerPointer(T) ||
1147       !Ctx.Idents.get("NS_RETURNS_INNER_POINTER").hasMacroDefinition())
1148     return;
1149   edit::Commit commit(*Editor);
1150   commit.insertBefore(P->getLocEnd(), " NS_RETURNS_INNER_POINTER ");
1151   Editor->commit(commit);
1152 }
1153
1154 void ObjCMigrateASTConsumer::migrateAllMethodInstaceType(ASTContext &Ctx,
1155                                                  ObjCContainerDecl *CDecl) {
1156   if (CDecl->isDeprecated())
1157     return;
1158   
1159   // migrate methods which can have instancetype as their result type.
1160   for (ObjCContainerDecl::method_iterator M = CDecl->meth_begin(),
1161        MEnd = CDecl->meth_end();
1162        M != MEnd; ++M) {
1163     ObjCMethodDecl *Method = (*M);
1164     if (Method->isDeprecated())
1165       continue;
1166     migrateMethodInstanceType(Ctx, CDecl, Method);
1167   }
1168 }
1169
1170 void ObjCMigrateASTConsumer::migrateFactoryMethod(ASTContext &Ctx,
1171                                                   ObjCContainerDecl *CDecl,
1172                                                   ObjCMethodDecl *OM,
1173                                                   ObjCInstanceTypeFamily OIT_Family) {
1174   if (OM->isInstanceMethod() ||
1175       OM->getResultType() == Ctx.getObjCInstanceType() ||
1176       !OM->getResultType()->isObjCIdType())
1177     return;
1178   
1179   // Candidate factory methods are + (id) NaMeXXX : ... which belong to a class
1180   // NSYYYNamE with matching names be at least 3 characters long.
1181   ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl);
1182   if (!IDecl) {
1183     if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl))
1184       IDecl = CatDecl->getClassInterface();
1185     else if (ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(CDecl))
1186       IDecl = ImpDecl->getClassInterface();
1187   }
1188   if (!IDecl)
1189     return;
1190   
1191   std::string StringClassName = IDecl->getName();
1192   StringRef LoweredClassName(StringClassName);
1193   std::string StringLoweredClassName = LoweredClassName.lower();
1194   LoweredClassName = StringLoweredClassName;
1195   
1196   IdentifierInfo *MethodIdName = OM->getSelector().getIdentifierInfoForSlot(0);
1197   // Handle method with no name at its first selector slot; e.g. + (id):(int)x.
1198   if (!MethodIdName)
1199     return;
1200   
1201   std::string MethodName = MethodIdName->getName();
1202   if (OIT_Family == OIT_Singleton || OIT_Family == OIT_ReturnsSelf) {
1203     StringRef STRefMethodName(MethodName);
1204     size_t len = 0;
1205     if (STRefMethodName.startswith("standard"))
1206       len = strlen("standard");
1207     else if (STRefMethodName.startswith("shared"))
1208       len = strlen("shared");
1209     else if (STRefMethodName.startswith("default"))
1210       len = strlen("default");
1211     else
1212       return;
1213     MethodName = STRefMethodName.substr(len);
1214   }
1215   std::string MethodNameSubStr = MethodName.substr(0, 3);
1216   StringRef MethodNamePrefix(MethodNameSubStr);
1217   std::string StringLoweredMethodNamePrefix = MethodNamePrefix.lower();
1218   MethodNamePrefix = StringLoweredMethodNamePrefix;
1219   size_t Ix = LoweredClassName.rfind(MethodNamePrefix);
1220   if (Ix == StringRef::npos)
1221     return;
1222   std::string ClassNamePostfix = LoweredClassName.substr(Ix);
1223   StringRef LoweredMethodName(MethodName);
1224   std::string StringLoweredMethodName = LoweredMethodName.lower();
1225   LoweredMethodName = StringLoweredMethodName;
1226   if (!LoweredMethodName.startswith(ClassNamePostfix))
1227     return;
1228   if (OIT_Family == OIT_ReturnsSelf)
1229     ReplaceWithClasstype(*this, OM);
1230   else
1231     ReplaceWithInstancetype(*this, OM);
1232 }
1233
1234 static bool IsVoidStarType(QualType Ty) {
1235   if (!Ty->isPointerType())
1236     return false;
1237   
1238   while (const TypedefType *TD = dyn_cast<TypedefType>(Ty.getTypePtr()))
1239     Ty = TD->getDecl()->getUnderlyingType();
1240   
1241   // Is the type void*?
1242   const PointerType* PT = Ty->getAs<PointerType>();
1243   if (PT->getPointeeType().getUnqualifiedType()->isVoidType())
1244     return true;
1245   return IsVoidStarType(PT->getPointeeType());
1246 }
1247
1248 /// AuditedType - This routine audits the type AT and returns false if it is one of known
1249 /// CF object types or of the "void *" variety. It returns true if we don't care about the type
1250 /// such as a non-pointer or pointers which have no ownership issues (such as "int *").
1251 static bool AuditedType (QualType AT) {
1252   if (!AT->isAnyPointerType() && !AT->isBlockPointerType())
1253     return true;
1254   // FIXME. There isn't much we can say about CF pointer type; or is there?
1255   if (ento::coreFoundation::isCFObjectRef(AT) ||
1256       IsVoidStarType(AT) ||
1257       // If an ObjC object is type, assuming that it is not a CF function and
1258       // that it is an un-audited function.
1259       AT->isObjCObjectPointerType() || AT->isObjCBuiltinType())
1260     return false;
1261   // All other pointers are assumed audited as harmless.
1262   return true;
1263 }
1264
1265 void ObjCMigrateASTConsumer::AnnotateImplicitBridging(ASTContext &Ctx) {
1266   if (CFFunctionIBCandidates.empty())
1267     return;
1268   if (!Ctx.Idents.get("CF_IMPLICIT_BRIDGING_ENABLED").hasMacroDefinition()) {
1269     CFFunctionIBCandidates.clear();
1270     FileId = FileID();
1271     return;
1272   }
1273   // Insert CF_IMPLICIT_BRIDGING_ENABLE/CF_IMPLICIT_BRIDGING_DISABLED
1274   const Decl *FirstFD = CFFunctionIBCandidates[0];
1275   const Decl *LastFD  =
1276     CFFunctionIBCandidates[CFFunctionIBCandidates.size()-1];
1277   const char *PragmaString = "\nCF_IMPLICIT_BRIDGING_ENABLED\n\n";
1278   edit::Commit commit(*Editor);
1279   commit.insertBefore(FirstFD->getLocStart(), PragmaString);
1280   PragmaString = "\n\nCF_IMPLICIT_BRIDGING_DISABLED\n";
1281   SourceLocation EndLoc = LastFD->getLocEnd();
1282   // get location just past end of function location.
1283   EndLoc = PP.getLocForEndOfToken(EndLoc);
1284   if (isa<FunctionDecl>(LastFD)) {
1285     // For Methods, EndLoc points to the ending semcolon. So,
1286     // not of these extra work is needed.
1287     Token Tok;
1288     // get locaiton of token that comes after end of function.
1289     bool Failed = PP.getRawToken(EndLoc, Tok, /*IgnoreWhiteSpace=*/true);
1290     if (!Failed)
1291       EndLoc = Tok.getLocation();
1292   }
1293   commit.insertAfterToken(EndLoc, PragmaString);
1294   Editor->commit(commit);
1295   FileId = FileID();
1296   CFFunctionIBCandidates.clear();
1297 }
1298
1299 void ObjCMigrateASTConsumer::migrateCFAnnotation(ASTContext &Ctx, const Decl *Decl) {
1300   if (Decl->isDeprecated())
1301     return;
1302   
1303   if (Decl->hasAttr<CFAuditedTransferAttr>()) {
1304     assert(CFFunctionIBCandidates.empty() &&
1305            "Cannot have audited functions/methods inside user "
1306            "provided CF_IMPLICIT_BRIDGING_ENABLE");
1307     return;
1308   }
1309   
1310   // Finction must be annotated first.
1311   if (const FunctionDecl *FuncDecl = dyn_cast<FunctionDecl>(Decl)) {
1312     CF_BRIDGING_KIND AuditKind = migrateAddFunctionAnnotation(Ctx, FuncDecl);
1313     if (AuditKind == CF_BRIDGING_ENABLE) {
1314       CFFunctionIBCandidates.push_back(Decl);
1315       if (FileId.isInvalid())
1316         FileId = PP.getSourceManager().getFileID(Decl->getLocation());
1317     }
1318     else if (AuditKind == CF_BRIDGING_MAY_INCLUDE) {
1319       if (!CFFunctionIBCandidates.empty()) {
1320         CFFunctionIBCandidates.push_back(Decl);
1321         if (FileId.isInvalid())
1322           FileId = PP.getSourceManager().getFileID(Decl->getLocation());
1323       }
1324     }
1325     else
1326       AnnotateImplicitBridging(Ctx);
1327   }
1328   else {
1329     migrateAddMethodAnnotation(Ctx, cast<ObjCMethodDecl>(Decl));
1330     AnnotateImplicitBridging(Ctx);
1331   }
1332 }
1333
1334 void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
1335                                               const CallEffects &CE,
1336                                               const FunctionDecl *FuncDecl,
1337                                               bool ResultAnnotated) {
1338   // Annotate function.
1339   if (!ResultAnnotated) {
1340     RetEffect Ret = CE.getReturnValue();
1341     const char *AnnotationString = 0;
1342     if (Ret.getObjKind() == RetEffect::CF) {
1343       if (Ret.isOwned() &&
1344           Ctx.Idents.get("CF_RETURNS_RETAINED").hasMacroDefinition())
1345         AnnotationString = " CF_RETURNS_RETAINED";
1346       else if (Ret.notOwned() &&
1347                Ctx.Idents.get("CF_RETURNS_NOT_RETAINED").hasMacroDefinition())
1348         AnnotationString = " CF_RETURNS_NOT_RETAINED";
1349     }
1350     else if (Ret.getObjKind() == RetEffect::ObjC) {
1351       if (Ret.isOwned() &&
1352           Ctx.Idents.get("NS_RETURNS_RETAINED").hasMacroDefinition())
1353         AnnotationString = " NS_RETURNS_RETAINED";
1354     }
1355     
1356     if (AnnotationString) {
1357       edit::Commit commit(*Editor);
1358       commit.insertAfterToken(FuncDecl->getLocEnd(), AnnotationString);
1359       Editor->commit(commit);
1360     }
1361   }
1362   llvm::ArrayRef<ArgEffect> AEArgs = CE.getArgs();
1363   unsigned i = 0;
1364   for (FunctionDecl::param_const_iterator pi = FuncDecl->param_begin(),
1365        pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) {
1366     const ParmVarDecl *pd = *pi;
1367     ArgEffect AE = AEArgs[i];
1368     if (AE == DecRef && !pd->getAttr<CFConsumedAttr>() &&
1369         Ctx.Idents.get("CF_CONSUMED").hasMacroDefinition()) {
1370       edit::Commit commit(*Editor);
1371       commit.insertBefore(pd->getLocation(), "CF_CONSUMED ");
1372       Editor->commit(commit);
1373     }
1374     else if (AE == DecRefMsg && !pd->getAttr<NSConsumedAttr>() &&
1375              Ctx.Idents.get("NS_CONSUMED").hasMacroDefinition()) {
1376       edit::Commit commit(*Editor);
1377       commit.insertBefore(pd->getLocation(), "NS_CONSUMED ");
1378       Editor->commit(commit);
1379     }
1380   }
1381 }
1382
1383
1384 ObjCMigrateASTConsumer::CF_BRIDGING_KIND
1385   ObjCMigrateASTConsumer::migrateAddFunctionAnnotation(
1386                                                   ASTContext &Ctx,
1387                                                   const FunctionDecl *FuncDecl) {
1388   if (FuncDecl->hasBody())
1389     return CF_BRIDGING_NONE;
1390     
1391   CallEffects CE  = CallEffects::getEffect(FuncDecl);
1392   bool FuncIsReturnAnnotated = (FuncDecl->getAttr<CFReturnsRetainedAttr>() ||
1393                                 FuncDecl->getAttr<CFReturnsNotRetainedAttr>() ||
1394                                 FuncDecl->getAttr<NSReturnsRetainedAttr>() ||
1395                                 FuncDecl->getAttr<NSReturnsNotRetainedAttr>() ||
1396                                 FuncDecl->getAttr<NSReturnsAutoreleasedAttr>());
1397   
1398   // Trivial case of when funciton is annotated and has no argument.
1399   if (FuncIsReturnAnnotated && FuncDecl->getNumParams() == 0)
1400     return CF_BRIDGING_NONE;
1401   
1402   bool ReturnCFAudited = false;
1403   if (!FuncIsReturnAnnotated) {
1404     RetEffect Ret = CE.getReturnValue();
1405     if (Ret.getObjKind() == RetEffect::CF &&
1406         (Ret.isOwned() || Ret.notOwned()))
1407       ReturnCFAudited = true;
1408     else if (!AuditedType(FuncDecl->getResultType()))
1409       return CF_BRIDGING_NONE;
1410   }
1411   
1412   // At this point result type is audited for potential inclusion.
1413   // Now, how about argument types.
1414   llvm::ArrayRef<ArgEffect> AEArgs = CE.getArgs();
1415   unsigned i = 0;
1416   bool ArgCFAudited = false;
1417   for (FunctionDecl::param_const_iterator pi = FuncDecl->param_begin(),
1418        pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) {
1419     const ParmVarDecl *pd = *pi;
1420     ArgEffect AE = AEArgs[i];
1421     if (AE == DecRef /*CFConsumed annotated*/ || AE == IncRef) {
1422       if (AE == DecRef && !pd->getAttr<CFConsumedAttr>())
1423         ArgCFAudited = true;
1424       else if (AE == IncRef)
1425         ArgCFAudited = true;
1426     }
1427     else {
1428       QualType AT = pd->getType();
1429       if (!AuditedType(AT)) {
1430         AddCFAnnotations(Ctx, CE, FuncDecl, FuncIsReturnAnnotated);
1431         return CF_BRIDGING_NONE;
1432       }
1433     }
1434   }
1435   if (ReturnCFAudited || ArgCFAudited)
1436     return CF_BRIDGING_ENABLE;
1437   
1438   return CF_BRIDGING_MAY_INCLUDE;
1439 }
1440
1441 void ObjCMigrateASTConsumer::migrateARCSafeAnnotation(ASTContext &Ctx,
1442                                                  ObjCContainerDecl *CDecl) {
1443   if (!isa<ObjCInterfaceDecl>(CDecl) || CDecl->isDeprecated())
1444     return;
1445   
1446   // migrate methods which can have instancetype as their result type.
1447   for (ObjCContainerDecl::method_iterator M = CDecl->meth_begin(),
1448        MEnd = CDecl->meth_end();
1449        M != MEnd; ++M) {
1450     ObjCMethodDecl *Method = (*M);
1451     migrateCFAnnotation(Ctx, Method);
1452   }
1453 }
1454
1455 void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
1456                                               const CallEffects &CE,
1457                                               const ObjCMethodDecl *MethodDecl,
1458                                               bool ResultAnnotated) {
1459   // Annotate function.
1460   if (!ResultAnnotated) {
1461     RetEffect Ret = CE.getReturnValue();
1462     const char *AnnotationString = 0;
1463     if (Ret.getObjKind() == RetEffect::CF) {
1464       if (Ret.isOwned() &&
1465           Ctx.Idents.get("CF_RETURNS_RETAINED").hasMacroDefinition())
1466         AnnotationString = " CF_RETURNS_RETAINED";
1467       else if (Ret.notOwned() &&
1468                Ctx.Idents.get("CF_RETURNS_NOT_RETAINED").hasMacroDefinition())
1469         AnnotationString = " CF_RETURNS_NOT_RETAINED";
1470     }
1471     else if (Ret.getObjKind() == RetEffect::ObjC) {
1472       ObjCMethodFamily OMF = MethodDecl->getMethodFamily();
1473       switch (OMF) {
1474         case clang::OMF_alloc:
1475         case clang::OMF_new:
1476         case clang::OMF_copy:
1477         case clang::OMF_init:
1478         case clang::OMF_mutableCopy:
1479           break;
1480           
1481         default:
1482           if (Ret.isOwned() &&
1483               Ctx.Idents.get("NS_RETURNS_RETAINED").hasMacroDefinition())
1484             AnnotationString = " NS_RETURNS_RETAINED";
1485           break;
1486       }
1487     }
1488     
1489     if (AnnotationString) {
1490       edit::Commit commit(*Editor);
1491       commit.insertBefore(MethodDecl->getLocEnd(), AnnotationString);
1492       Editor->commit(commit);
1493     }
1494   }
1495   llvm::ArrayRef<ArgEffect> AEArgs = CE.getArgs();
1496   unsigned i = 0;
1497   for (ObjCMethodDecl::param_const_iterator pi = MethodDecl->param_begin(),
1498        pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) {
1499     const ParmVarDecl *pd = *pi;
1500     ArgEffect AE = AEArgs[i];
1501     if (AE == DecRef && !pd->getAttr<CFConsumedAttr>() &&
1502         Ctx.Idents.get("CF_CONSUMED").hasMacroDefinition()) {
1503       edit::Commit commit(*Editor);
1504       commit.insertBefore(pd->getLocation(), "CF_CONSUMED ");
1505       Editor->commit(commit);
1506     }
1507   }
1508 }
1509
1510 void ObjCMigrateASTConsumer::migrateAddMethodAnnotation(
1511                                             ASTContext &Ctx,
1512                                             const ObjCMethodDecl *MethodDecl) {
1513   if (MethodDecl->hasBody() || MethodDecl->isImplicit())
1514     return;
1515   
1516   CallEffects CE  = CallEffects::getEffect(MethodDecl);
1517   bool MethodIsReturnAnnotated = (MethodDecl->getAttr<CFReturnsRetainedAttr>() ||
1518                                   MethodDecl->getAttr<CFReturnsNotRetainedAttr>() ||
1519                                   MethodDecl->getAttr<NSReturnsRetainedAttr>() ||
1520                                   MethodDecl->getAttr<NSReturnsNotRetainedAttr>() ||
1521                                   MethodDecl->getAttr<NSReturnsAutoreleasedAttr>());
1522   
1523   if (CE.getReceiver() ==  DecRefMsg &&
1524       !MethodDecl->getAttr<NSConsumesSelfAttr>() &&
1525       MethodDecl->getMethodFamily() != OMF_init &&
1526       MethodDecl->getMethodFamily() != OMF_release &&
1527       Ctx.Idents.get("NS_CONSUMES_SELF").hasMacroDefinition()) {
1528     edit::Commit commit(*Editor);
1529     commit.insertBefore(MethodDecl->getLocEnd(), " NS_CONSUMES_SELF");
1530     Editor->commit(commit);
1531   }
1532   
1533   // Trivial case of when funciton is annotated and has no argument.
1534   if (MethodIsReturnAnnotated &&
1535       (MethodDecl->param_begin() == MethodDecl->param_end()))
1536     return;
1537   
1538   if (!MethodIsReturnAnnotated) {
1539     RetEffect Ret = CE.getReturnValue();
1540     if ((Ret.getObjKind() == RetEffect::CF ||
1541          Ret.getObjKind() == RetEffect::ObjC) &&
1542         (Ret.isOwned() || Ret.notOwned())) {
1543       AddCFAnnotations(Ctx, CE, MethodDecl, false);
1544       return;
1545     }
1546     else if (!AuditedType(MethodDecl->getResultType()))
1547       return;
1548   }
1549   
1550   // At this point result type is either annotated or audited.
1551   // Now, how about argument types.
1552   llvm::ArrayRef<ArgEffect> AEArgs = CE.getArgs();
1553   unsigned i = 0;
1554   for (ObjCMethodDecl::param_const_iterator pi = MethodDecl->param_begin(),
1555        pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) {
1556     const ParmVarDecl *pd = *pi;
1557     ArgEffect AE = AEArgs[i];
1558     if ((AE == DecRef && !pd->getAttr<CFConsumedAttr>()) || AE == IncRef ||
1559         !AuditedType(pd->getType())) {
1560       AddCFAnnotations(Ctx, CE, MethodDecl, MethodIsReturnAnnotated);
1561       return;
1562     }
1563   }
1564   return;
1565 }
1566
1567 namespace {
1568
1569 class RewritesReceiver : public edit::EditsReceiver {
1570   Rewriter &Rewrite;
1571
1572 public:
1573   RewritesReceiver(Rewriter &Rewrite) : Rewrite(Rewrite) { }
1574
1575   virtual void insert(SourceLocation loc, StringRef text) {
1576     Rewrite.InsertText(loc, text);
1577   }
1578   virtual void replace(CharSourceRange range, StringRef text) {
1579     Rewrite.ReplaceText(range.getBegin(), Rewrite.getRangeSize(range), text);
1580   }
1581 };
1582
1583 }
1584
1585 static bool
1586 IsReallyASystemHeader(ASTContext &Ctx, const FileEntry *file, FileID FID) {
1587   bool Invalid = false;
1588   const SrcMgr::SLocEntry &SEntry =
1589   Ctx.getSourceManager().getSLocEntry(FID, &Invalid);
1590   if (!Invalid && SEntry.isFile()) {
1591     const SrcMgr::FileInfo &FI = SEntry.getFile();
1592     if (!FI.hasLineDirectives()) {
1593       if (FI.getFileCharacteristic() == SrcMgr::C_ExternCSystem)
1594         return true;
1595       if (FI.getFileCharacteristic() == SrcMgr::C_System) {
1596         // This file is in a system header directory. Continue with commiting change
1597         // only if it is a user specified system directory because user put a
1598         // .system_framework file in the framework directory.
1599         StringRef Directory(file->getDir()->getName());
1600         size_t Ix = Directory.rfind(".framework");
1601         if (Ix == StringRef::npos)
1602           return true;
1603         std::string PatchToSystemFramework = Directory.slice(0, Ix+sizeof(".framework"));
1604         PatchToSystemFramework += ".system_framework";
1605         if (!llvm::sys::fs::exists(PatchToSystemFramework.data()))
1606           return true;
1607       }
1608     }
1609   }
1610   return false;
1611 }
1612
1613 void ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) {
1614   
1615   TranslationUnitDecl *TU = Ctx.getTranslationUnitDecl();
1616   if (ASTMigrateActions & FrontendOptions::ObjCMT_MigrateDecls) {
1617     for (DeclContext::decl_iterator D = TU->decls_begin(), DEnd = TU->decls_end();
1618          D != DEnd; ++D) {
1619       FileID FID = PP.getSourceManager().getFileID((*D)->getLocation());
1620       if (!FID.isInvalid())
1621         if (!FileId.isInvalid() && FileId != FID) {
1622           if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation)
1623             AnnotateImplicitBridging(Ctx);
1624         }
1625       
1626       if (ObjCInterfaceDecl *CDecl = dyn_cast<ObjCInterfaceDecl>(*D))
1627         migrateObjCInterfaceDecl(Ctx, CDecl);
1628       if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(*D)) {
1629         migrateObjCInterfaceDecl(Ctx, CatDecl);
1630         if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation)
1631           migrateDeprecatedAnnotation(Ctx, CatDecl);
1632       }
1633       else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(*D))
1634         ObjCProtocolDecls.insert(PDecl);
1635       else if (const ObjCImplementationDecl *ImpDecl =
1636                dyn_cast<ObjCImplementationDecl>(*D)) {
1637         if (ASTMigrateActions & FrontendOptions::ObjCMT_ProtocolConformance)
1638           migrateProtocolConformance(Ctx, ImpDecl);
1639       }
1640       else if (const EnumDecl *ED = dyn_cast<EnumDecl>(*D)) {
1641         if (!(ASTMigrateActions & FrontendOptions::ObjCMT_NsMacros))
1642           continue;
1643         DeclContext::decl_iterator N = D;
1644         if (++N != DEnd) {
1645           const TypedefDecl *TD = dyn_cast<TypedefDecl>(*N);
1646           if (migrateNSEnumDecl(Ctx, ED, TD) && TD)
1647             D++;
1648         }
1649         else
1650           migrateNSEnumDecl(Ctx, ED, /*TypedefDecl */0);
1651       }
1652       else if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(*D)) {
1653         if (!(ASTMigrateActions & FrontendOptions::ObjCMT_NsMacros))
1654           continue;
1655         DeclContext::decl_iterator N = D;
1656         if (++N == DEnd)
1657           continue;
1658         if (const EnumDecl *ED = dyn_cast<EnumDecl>(*N)) {
1659           if (++N != DEnd)
1660             if (const TypedefDecl *TDF = dyn_cast<TypedefDecl>(*N)) {
1661               // prefer typedef-follows-enum to enum-follows-typedef pattern.
1662               if (migrateNSEnumDecl(Ctx, ED, TDF)) {
1663                 ++D; ++D;
1664                 CacheObjCNSIntegerTypedefed(TD);
1665                 continue;
1666               }
1667             }
1668           if (migrateNSEnumDecl(Ctx, ED, TD)) {
1669             ++D;
1670             continue;
1671           }
1672         }
1673         CacheObjCNSIntegerTypedefed(TD);
1674       }
1675       else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*D)) {
1676         if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation)
1677           migrateCFAnnotation(Ctx, FD);
1678       }
1679       
1680       if (ObjCContainerDecl *CDecl = dyn_cast<ObjCContainerDecl>(*D)) {
1681         // migrate methods which can have instancetype as their result type.
1682         if (ASTMigrateActions & FrontendOptions::ObjCMT_Instancetype)
1683           migrateAllMethodInstaceType(Ctx, CDecl);
1684         // annotate methods with CF annotations.
1685         if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation)
1686           migrateARCSafeAnnotation(Ctx, CDecl);
1687       }
1688     }
1689     if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation)
1690       AnnotateImplicitBridging(Ctx);
1691   }
1692   
1693   Rewriter rewriter(Ctx.getSourceManager(), Ctx.getLangOpts());
1694   RewritesReceiver Rec(rewriter);
1695   Editor->applyRewrites(Rec);
1696
1697   for (Rewriter::buffer_iterator
1698         I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) {
1699     FileID FID = I->first;
1700     RewriteBuffer &buf = I->second;
1701     const FileEntry *file = Ctx.getSourceManager().getFileEntryForID(FID);
1702     assert(file);
1703     if (IsReallyASystemHeader(Ctx, file, FID))
1704       continue;
1705     if (!canModifyFile(file->getName()))
1706       continue;
1707     SmallString<512> newText;
1708     llvm::raw_svector_ostream vecOS(newText);
1709     buf.write(vecOS);
1710     vecOS.flush();
1711     llvm::MemoryBuffer *memBuf = llvm::MemoryBuffer::getMemBufferCopy(
1712                    StringRef(newText.data(), newText.size()), file->getName());
1713     SmallString<64> filePath(file->getName());
1714     FileMgr.FixupRelativePath(filePath);
1715     Remapper.remap(filePath.str(), memBuf);
1716   }
1717
1718   if (IsOutputFile) {
1719     Remapper.flushToFile(MigrateDir, Ctx.getDiagnostics());
1720   } else {
1721     Remapper.flushToDisk(MigrateDir, Ctx.getDiagnostics());
1722   }
1723 }
1724
1725 bool MigrateSourceAction::BeginInvocation(CompilerInstance &CI) {
1726   CI.getDiagnostics().setIgnoreAllWarnings(true);
1727   return true;
1728 }
1729
1730 static std::vector<std::string> getWhiteListFilenames(StringRef DirPath) {
1731   using namespace llvm::sys::fs;
1732   using namespace llvm::sys::path;
1733
1734   std::vector<std::string> Filenames;
1735   if (DirPath.empty() || !is_directory(DirPath))
1736     return Filenames;
1737   
1738   llvm::error_code EC;
1739   directory_iterator DI = directory_iterator(DirPath, EC);
1740   directory_iterator DE;
1741   for (; !EC && DI != DE; DI = DI.increment(EC)) {
1742     if (is_regular_file(DI->path()))
1743       Filenames.push_back(filename(DI->path()));
1744   }
1745
1746   return Filenames;
1747 }
1748
1749 ASTConsumer *MigrateSourceAction::CreateASTConsumer(CompilerInstance &CI,
1750                                                   StringRef InFile) {
1751   PPConditionalDirectiveRecord *
1752     PPRec = new PPConditionalDirectiveRecord(CI.getSourceManager());
1753   unsigned ObjCMTAction = CI.getFrontendOpts().ObjCMTAction;
1754   unsigned ObjCMTOpts = ObjCMTAction;
1755   // These are companion flags, they do not enable transformations.
1756   ObjCMTOpts &= ~(FrontendOptions::ObjCMT_AtomicProperty |
1757                   FrontendOptions::ObjCMT_NsAtomicIOSOnlyProperty);
1758   if (ObjCMTOpts == FrontendOptions::ObjCMT_None) {
1759     // If no specific option was given, enable literals+subscripting transforms
1760     // by default.
1761     ObjCMTAction |= FrontendOptions::ObjCMT_Literals |
1762                     FrontendOptions::ObjCMT_Subscripting;
1763   }
1764   CI.getPreprocessor().addPPCallbacks(PPRec);
1765   std::vector<std::string> WhiteList =
1766     getWhiteListFilenames(CI.getFrontendOpts().ObjCMTWhiteListPath);
1767   return new ObjCMigrateASTConsumer(CI.getFrontendOpts().OutputFile,
1768                                     ObjCMTAction,
1769                                     Remapper,
1770                                     CI.getFileManager(),
1771                                     PPRec,
1772                                     CI.getPreprocessor(),
1773                                     /*isOutputFile=*/true,
1774                                     WhiteList);
1775 }