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