ObjCMT.cpp revision d0f2921c3211299a80c043a3251e6b34dddba061
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, ObjCInterfaceDecl *D);
47  void migrateProtocolConformance(ASTContext &Ctx,
48                                  const ObjCImplementationDecl *ImpDecl);
49  void migrateNSEnumDecl(ASTContext &Ctx, const EnumDecl *EnumDcl,
50                     const TypedefDecl *TypedefDcl);
51  void migrateInstanceType(ASTContext &Ctx, ObjCContainerDecl *CDecl);
52  void migrateMethodInstanceType(ASTContext &Ctx, ObjCContainerDecl *CDecl,
53                                 ObjCMethodDecl *OM);
54  void migrateFactoryMethod(ASTContext &Ctx, ObjCContainerDecl *CDecl,
55                            ObjCMethodDecl *OM,
56                            ObjCInstanceTypeFamily OIT_Family = OIT_None);
57
58  void migrateCFAnnotation(ASTContext &Ctx, const Decl *Decl);
59  void AddCFAnnotations(ASTContext &Ctx, const CallEffects &CE,
60                        const FunctionDecl *FuncDecl, bool ResultAnnotated);
61  void AddCFAnnotations(ASTContext &Ctx, const CallEffects &CE,
62                        const ObjCMethodDecl *MethodDecl, bool ResultAnnotated);
63
64  void AnnotateImplicitBridging(ASTContext &Ctx);
65
66  CF_BRIDGING_KIND migrateAddFunctionAnnotation(ASTContext &Ctx,
67                                                const FunctionDecl *FuncDecl);
68
69  void migrateARCSafeAnnotation(ASTContext &Ctx, ObjCContainerDecl *CDecl);
70
71  CF_BRIDGING_KIND migrateAddMethodAnnotation(ASTContext &Ctx,
72                                              const ObjCMethodDecl *MethodDecl);
73public:
74  std::string MigrateDir;
75  bool MigrateLiterals;
76  bool MigrateSubscripting;
77  bool MigrateProperty;
78  bool MigrateReadonlyProperty;
79  unsigned  FileId;
80  OwningPtr<NSAPI> NSAPIObj;
81  OwningPtr<edit::EditedSource> Editor;
82  FileRemapper &Remapper;
83  FileManager &FileMgr;
84  const PPConditionalDirectiveRecord *PPRec;
85  Preprocessor &PP;
86  bool IsOutputFile;
87  llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ObjCProtocolDecls;
88  llvm::SmallVector<const Decl *, 8> CFFunctionIBCandidates;
89
90  ObjCMigrateASTConsumer(StringRef migrateDir,
91                         bool migrateLiterals,
92                         bool migrateSubscripting,
93                         bool migrateProperty,
94                         bool migrateReadonlyProperty,
95                         FileRemapper &remapper,
96                         FileManager &fileMgr,
97                         const PPConditionalDirectiveRecord *PPRec,
98                         Preprocessor &PP,
99                         bool isOutputFile = false)
100  : MigrateDir(migrateDir),
101    MigrateLiterals(migrateLiterals),
102    MigrateSubscripting(migrateSubscripting),
103    MigrateProperty(migrateProperty),
104    MigrateReadonlyProperty(migrateReadonlyProperty),
105    FileId(0), Remapper(remapper), FileMgr(fileMgr), PPRec(PPRec), PP(PP),
106    IsOutputFile(isOutputFile) { }
107
108protected:
109  virtual void Initialize(ASTContext &Context) {
110    NSAPIObj.reset(new NSAPI(Context));
111    Editor.reset(new edit::EditedSource(Context.getSourceManager(),
112                                        Context.getLangOpts(),
113                                        PPRec));
114  }
115
116  virtual bool HandleTopLevelDecl(DeclGroupRef DG) {
117    for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
118      migrateDecl(*I);
119    return true;
120  }
121  virtual void HandleInterestingDecl(DeclGroupRef DG) {
122    // Ignore decls from the PCH.
123  }
124  virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) {
125    ObjCMigrateASTConsumer::HandleTopLevelDecl(DG);
126  }
127
128  virtual void HandleTranslationUnit(ASTContext &Ctx);
129};
130
131}
132
133ObjCMigrateAction::ObjCMigrateAction(FrontendAction *WrappedAction,
134                             StringRef migrateDir,
135                             bool migrateLiterals,
136                             bool migrateSubscripting,
137                             bool migrateProperty,
138                             bool migrateReadonlyProperty)
139  : WrapperFrontendAction(WrappedAction), MigrateDir(migrateDir),
140    MigrateLiterals(migrateLiterals), MigrateSubscripting(migrateSubscripting),
141    MigrateProperty(migrateProperty),
142    MigrateReadonlyProperty(migrateReadonlyProperty),
143    CompInst(0) {
144  if (MigrateDir.empty())
145    MigrateDir = "."; // user current directory if none is given.
146}
147
148ASTConsumer *ObjCMigrateAction::CreateASTConsumer(CompilerInstance &CI,
149                                                  StringRef InFile) {
150  PPConditionalDirectiveRecord *
151    PPRec = new PPConditionalDirectiveRecord(CompInst->getSourceManager());
152  CompInst->getPreprocessor().addPPCallbacks(PPRec);
153  ASTConsumer *
154    WrappedConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile);
155  ASTConsumer *MTConsumer = new ObjCMigrateASTConsumer(MigrateDir,
156                                                       MigrateLiterals,
157                                                       MigrateSubscripting,
158                                                       MigrateProperty,
159                                                       MigrateReadonlyProperty,
160                                                       Remapper,
161                                                    CompInst->getFileManager(),
162                                                       PPRec,
163                                                       CompInst->getPreprocessor());
164  ASTConsumer *Consumers[] = { MTConsumer, WrappedConsumer };
165  return new MultiplexConsumer(Consumers);
166}
167
168bool ObjCMigrateAction::BeginInvocation(CompilerInstance &CI) {
169  Remapper.initFromDisk(MigrateDir, CI.getDiagnostics(),
170                        /*ignoreIfFilesChanges=*/true);
171  CompInst = &CI;
172  CI.getDiagnostics().setIgnoreAllWarnings(true);
173  return true;
174}
175
176namespace {
177class ObjCMigrator : public RecursiveASTVisitor<ObjCMigrator> {
178  ObjCMigrateASTConsumer &Consumer;
179  ParentMap &PMap;
180
181public:
182  ObjCMigrator(ObjCMigrateASTConsumer &consumer, ParentMap &PMap)
183    : Consumer(consumer), PMap(PMap) { }
184
185  bool shouldVisitTemplateInstantiations() const { return false; }
186  bool shouldWalkTypesOfTypeLocs() const { return false; }
187
188  bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
189    if (Consumer.MigrateLiterals) {
190      edit::Commit commit(*Consumer.Editor);
191      edit::rewriteToObjCLiteralSyntax(E, *Consumer.NSAPIObj, commit, &PMap);
192      Consumer.Editor->commit(commit);
193    }
194
195    if (Consumer.MigrateSubscripting) {
196      edit::Commit commit(*Consumer.Editor);
197      edit::rewriteToObjCSubscriptSyntax(E, *Consumer.NSAPIObj, commit);
198      Consumer.Editor->commit(commit);
199    }
200
201    return true;
202  }
203
204  bool TraverseObjCMessageExpr(ObjCMessageExpr *E) {
205    // Do depth first; we want to rewrite the subexpressions first so that if
206    // we have to move expressions we will move them already rewritten.
207    for (Stmt::child_range range = E->children(); range; ++range)
208      if (!TraverseStmt(*range))
209        return false;
210
211    return WalkUpFromObjCMessageExpr(E);
212  }
213};
214
215class BodyMigrator : public RecursiveASTVisitor<BodyMigrator> {
216  ObjCMigrateASTConsumer &Consumer;
217  OwningPtr<ParentMap> PMap;
218
219public:
220  BodyMigrator(ObjCMigrateASTConsumer &consumer) : Consumer(consumer) { }
221
222  bool shouldVisitTemplateInstantiations() const { return false; }
223  bool shouldWalkTypesOfTypeLocs() const { return false; }
224
225  bool TraverseStmt(Stmt *S) {
226    PMap.reset(new ParentMap(S));
227    ObjCMigrator(Consumer, *PMap).TraverseStmt(S);
228    return true;
229  }
230};
231}
232
233void ObjCMigrateASTConsumer::migrateDecl(Decl *D) {
234  if (!D)
235    return;
236  if (isa<ObjCMethodDecl>(D))
237    return; // Wait for the ObjC container declaration.
238
239  BodyMigrator(*this).TraverseDecl(D);
240}
241
242static void append_attr(std::string &PropertyString, const char *attr) {
243  PropertyString += ", ";
244  PropertyString += attr;
245}
246
247static bool rewriteToObjCProperty(const ObjCMethodDecl *Getter,
248                                  const ObjCMethodDecl *Setter,
249                                  const NSAPI &NS, edit::Commit &commit,
250                                  bool GetterHasIsPrefix) {
251  ASTContext &Context = NS.getASTContext();
252  std::string PropertyString = "@property(nonatomic";
253  std::string PropertyNameString = Getter->getNameAsString();
254  StringRef PropertyName(PropertyNameString);
255  if (GetterHasIsPrefix) {
256    PropertyString += ", getter=";
257    PropertyString += PropertyNameString;
258  }
259  // Property with no setter may be suggested as a 'readonly' property.
260  if (!Setter)
261    append_attr(PropertyString, "readonly");
262
263  // Short circuit properties that contain the name "delegate" or "dataSource",
264  // or have exact name "target" to have unsafe_unretained attribute.
265  if (PropertyName.equals("target") ||
266      (PropertyName.find("delegate") != StringRef::npos) ||
267      (PropertyName.find("dataSource") != StringRef::npos))
268    append_attr(PropertyString, "unsafe_unretained");
269  else if (Setter) {
270    const ParmVarDecl *argDecl = *Setter->param_begin();
271    QualType ArgType = Context.getCanonicalType(argDecl->getType());
272    Qualifiers::ObjCLifetime propertyLifetime = ArgType.getObjCLifetime();
273    bool RetainableObject = ArgType->isObjCRetainableType();
274    if (RetainableObject && propertyLifetime == Qualifiers::OCL_Strong) {
275      if (const ObjCObjectPointerType *ObjPtrTy =
276          ArgType->getAs<ObjCObjectPointerType>()) {
277        ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface();
278        if (IDecl &&
279            IDecl->lookupNestedProtocol(&Context.Idents.get("NSCopying")))
280          append_attr(PropertyString, "copy");
281        else
282          append_attr(PropertyString, "retain");
283      }
284    } else if (propertyLifetime == Qualifiers::OCL_Weak)
285      // TODO. More precise determination of 'weak' attribute requires
286      // looking into setter's implementation for backing weak ivar.
287      append_attr(PropertyString, "weak");
288    else if (RetainableObject)
289      append_attr(PropertyString, "retain");
290  }
291  PropertyString += ')';
292
293  QualType RT = Getter->getResultType();
294  if (!isa<TypedefType>(RT)) {
295    // strip off any ARC lifetime qualifier.
296    QualType CanResultTy = Context.getCanonicalType(RT);
297    if (CanResultTy.getQualifiers().hasObjCLifetime()) {
298      Qualifiers Qs = CanResultTy.getQualifiers();
299      Qs.removeObjCLifetime();
300      RT = Context.getQualifiedType(CanResultTy.getUnqualifiedType(), Qs);
301    }
302  }
303  PropertyString += " ";
304  PropertyString += RT.getAsString(Context.getPrintingPolicy());
305  PropertyString += " ";
306  if (GetterHasIsPrefix) {
307    // property name must strip off "is" and lower case the first character
308    // after that; e.g. isContinuous will become continuous.
309    StringRef PropertyNameStringRef(PropertyNameString);
310    PropertyNameStringRef = PropertyNameStringRef.drop_front(2);
311    PropertyNameString = PropertyNameStringRef;
312    std::string NewPropertyNameString = PropertyNameString;
313    NewPropertyNameString[0] = toLowercase(NewPropertyNameString[0]);
314    PropertyString += NewPropertyNameString;
315  }
316  else
317    PropertyString += PropertyNameString;
318  commit.replace(CharSourceRange::getCharRange(Getter->getLocStart(),
319                                               Getter->getDeclaratorEndLoc()),
320                 PropertyString);
321  if (Setter) {
322    SourceLocation EndLoc = Setter->getDeclaratorEndLoc();
323    // Get location past ';'
324    EndLoc = EndLoc.getLocWithOffset(1);
325    commit.remove(CharSourceRange::getCharRange(Setter->getLocStart(), EndLoc));
326  }
327  return true;
328}
329
330void ObjCMigrateASTConsumer::migrateObjCInterfaceDecl(ASTContext &Ctx,
331                                                      ObjCInterfaceDecl *D) {
332  for (ObjCContainerDecl::method_iterator M = D->meth_begin(), MEnd = D->meth_end();
333       M != MEnd; ++M) {
334    ObjCMethodDecl *Method = (*M);
335    if (Method->isPropertyAccessor() || !Method->isInstanceMethod() ||
336        Method->param_size() != 0)
337      continue;
338    // Is this method candidate to be a getter?
339    QualType GRT = Method->getResultType();
340    if (GRT->isVoidType())
341      continue;
342    // FIXME. Don't know what todo with attributes, skip for now.
343    if (Method->hasAttrs())
344      continue;
345
346    Selector GetterSelector = Method->getSelector();
347    IdentifierInfo *getterName = GetterSelector.getIdentifierInfoForSlot(0);
348    Selector SetterSelector =
349      SelectorTable::constructSetterSelector(PP.getIdentifierTable(),
350                                             PP.getSelectorTable(),
351                                             getterName);
352    ObjCMethodDecl *SetterMethod = D->lookupMethod(SetterSelector, true);
353    bool GetterHasIsPrefix = false;
354    if (!SetterMethod) {
355      // try a different naming convention for getter: isXxxxx
356      StringRef getterNameString = getterName->getName();
357      if (getterNameString.startswith("is") && !GRT->isObjCRetainableType()) {
358        GetterHasIsPrefix = true;
359        const char *CGetterName = getterNameString.data() + 2;
360        if (CGetterName[0] && isUppercase(CGetterName[0])) {
361          getterName = &Ctx.Idents.get(CGetterName);
362          SetterSelector =
363            SelectorTable::constructSetterSelector(PP.getIdentifierTable(),
364                                                   PP.getSelectorTable(),
365                                                   getterName);
366          SetterMethod = D->lookupMethod(SetterSelector, true);
367        }
368      }
369    }
370    if (SetterMethod) {
371      // Is this a valid setter, matching the target getter?
372      QualType SRT = SetterMethod->getResultType();
373      if (!SRT->isVoidType())
374        continue;
375      const ParmVarDecl *argDecl = *SetterMethod->param_begin();
376      QualType ArgType = argDecl->getType();
377      if (!Ctx.hasSameUnqualifiedType(ArgType, GRT) ||
378          SetterMethod->hasAttrs())
379          continue;
380        edit::Commit commit(*Editor);
381        rewriteToObjCProperty(Method, SetterMethod, *NSAPIObj, commit,
382                              GetterHasIsPrefix);
383        Editor->commit(commit);
384    }
385    else if (MigrateReadonlyProperty) {
386      // Try a non-void method with no argument (and no setter or property of same name
387      // as a 'readonly' property.
388      edit::Commit commit(*Editor);
389      rewriteToObjCProperty(Method, 0 /*SetterMethod*/, *NSAPIObj, commit,
390                            false /*GetterHasIsPrefix*/);
391      Editor->commit(commit);
392    }
393  }
394}
395
396static bool
397ClassImplementsAllMethodsAndProperties(ASTContext &Ctx,
398                                      const ObjCImplementationDecl *ImpDecl,
399                                       const ObjCInterfaceDecl *IDecl,
400                                      ObjCProtocolDecl *Protocol) {
401  // In auto-synthesis, protocol properties are not synthesized. So,
402  // a conforming protocol must have its required properties declared
403  // in class interface.
404  bool HasAtleastOneRequiredProperty = false;
405  if (const ObjCProtocolDecl *PDecl = Protocol->getDefinition())
406    for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
407         E = PDecl->prop_end(); P != E; ++P) {
408      ObjCPropertyDecl *Property = *P;
409      if (Property->getPropertyImplementation() == ObjCPropertyDecl::Optional)
410        continue;
411      HasAtleastOneRequiredProperty = true;
412      DeclContext::lookup_const_result R = IDecl->lookup(Property->getDeclName());
413      if (R.size() == 0) {
414        // Relax the rule and look into class's implementation for a synthesize
415        // or dynamic declaration. Class is implementing a property coming from
416        // another protocol. This still makes the target protocol as conforming.
417        if (!ImpDecl->FindPropertyImplDecl(
418                                  Property->getDeclName().getAsIdentifierInfo()))
419          return false;
420      }
421      else if (ObjCPropertyDecl *ClassProperty = dyn_cast<ObjCPropertyDecl>(R[0])) {
422          if ((ClassProperty->getPropertyAttributes()
423              != Property->getPropertyAttributes()) ||
424              !Ctx.hasSameType(ClassProperty->getType(), Property->getType()))
425            return false;
426      }
427      else
428        return false;
429    }
430
431  // At this point, all required properties in this protocol conform to those
432  // declared in the class.
433  // Check that class implements the required methods of the protocol too.
434  bool HasAtleastOneRequiredMethod = false;
435  if (const ObjCProtocolDecl *PDecl = Protocol->getDefinition()) {
436    if (PDecl->meth_begin() == PDecl->meth_end())
437      return HasAtleastOneRequiredProperty;
438    for (ObjCContainerDecl::method_iterator M = PDecl->meth_begin(),
439         MEnd = PDecl->meth_end(); M != MEnd; ++M) {
440      ObjCMethodDecl *MD = (*M);
441      if (MD->isImplicit())
442        continue;
443      if (MD->getImplementationControl() == ObjCMethodDecl::Optional)
444        continue;
445      DeclContext::lookup_const_result R = ImpDecl->lookup(MD->getDeclName());
446      if (R.size() == 0)
447        return false;
448      bool match = false;
449      HasAtleastOneRequiredMethod = true;
450      for (unsigned I = 0, N = R.size(); I != N; ++I)
451        if (ObjCMethodDecl *ImpMD = dyn_cast<ObjCMethodDecl>(R[0]))
452          if (Ctx.ObjCMethodsAreEqual(MD, ImpMD)) {
453            match = true;
454            break;
455          }
456      if (!match)
457        return false;
458    }
459  }
460  if (HasAtleastOneRequiredProperty || HasAtleastOneRequiredMethod)
461    return true;
462  return false;
463}
464
465static bool rewriteToObjCInterfaceDecl(const ObjCInterfaceDecl *IDecl,
466                    llvm::SmallVectorImpl<ObjCProtocolDecl*> &ConformingProtocols,
467                    const NSAPI &NS, edit::Commit &commit) {
468  const ObjCList<ObjCProtocolDecl> &Protocols = IDecl->getReferencedProtocols();
469  std::string ClassString;
470  SourceLocation EndLoc =
471  IDecl->getSuperClass() ? IDecl->getSuperClassLoc() : IDecl->getLocation();
472
473  if (Protocols.empty()) {
474    ClassString = '<';
475    for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
476      ClassString += ConformingProtocols[i]->getNameAsString();
477      if (i != (e-1))
478        ClassString += ", ";
479    }
480    ClassString += "> ";
481  }
482  else {
483    ClassString = ", ";
484    for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
485      ClassString += ConformingProtocols[i]->getNameAsString();
486      if (i != (e-1))
487        ClassString += ", ";
488    }
489    ObjCInterfaceDecl::protocol_loc_iterator PL = IDecl->protocol_loc_end() - 1;
490    EndLoc = *PL;
491  }
492
493  commit.insertAfterToken(EndLoc, ClassString);
494  return true;
495}
496
497static bool rewriteToNSEnumDecl(const EnumDecl *EnumDcl,
498                                const TypedefDecl *TypedefDcl,
499                                const NSAPI &NS, edit::Commit &commit,
500                                bool IsNSIntegerType) {
501  std::string ClassString =
502    IsNSIntegerType ? "typedef NS_ENUM(NSInteger, " : "typedef NS_OPTIONS(NSUInteger, ";
503  ClassString += TypedefDcl->getIdentifier()->getName();
504  ClassString += ')';
505  SourceRange R(EnumDcl->getLocStart(), EnumDcl->getLocStart());
506  commit.replace(R, ClassString);
507  SourceLocation EndOfTypedefLoc = TypedefDcl->getLocEnd();
508  EndOfTypedefLoc = trans::findLocationAfterSemi(EndOfTypedefLoc, NS.getASTContext());
509  if (!EndOfTypedefLoc.isInvalid()) {
510    commit.remove(SourceRange(TypedefDcl->getLocStart(), EndOfTypedefLoc));
511    return true;
512  }
513  return false;
514}
515
516static bool rewriteToNSMacroDecl(const EnumDecl *EnumDcl,
517                                const TypedefDecl *TypedefDcl,
518                                const NSAPI &NS, edit::Commit &commit,
519                                 bool IsNSIntegerType) {
520  std::string ClassString =
521    IsNSIntegerType ? "NS_ENUM(NSInteger, " : "NS_OPTIONS(NSUInteger, ";
522  ClassString += TypedefDcl->getIdentifier()->getName();
523  ClassString += ')';
524  SourceRange R(EnumDcl->getLocStart(), EnumDcl->getLocStart());
525  commit.replace(R, ClassString);
526  SourceLocation TypedefLoc = TypedefDcl->getLocEnd();
527  commit.remove(SourceRange(TypedefLoc, TypedefLoc));
528  return true;
529}
530
531static bool UseNSOptionsMacro(ASTContext &Ctx,
532                              const EnumDecl *EnumDcl) {
533  bool PowerOfTwo = true;
534  uint64_t MaxPowerOfTwoVal = 0;
535  for (EnumDecl::enumerator_iterator EI = EnumDcl->enumerator_begin(),
536       EE = EnumDcl->enumerator_end(); EI != EE; ++EI) {
537    EnumConstantDecl *Enumerator = (*EI);
538    const Expr *InitExpr = Enumerator->getInitExpr();
539    if (!InitExpr) {
540      PowerOfTwo = false;
541      continue;
542    }
543    InitExpr = InitExpr->IgnoreImpCasts();
544    if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(InitExpr))
545      if (BO->isShiftOp() || BO->isBitwiseOp())
546        return true;
547
548    uint64_t EnumVal = Enumerator->getInitVal().getZExtValue();
549    if (PowerOfTwo && EnumVal) {
550      if (!llvm::isPowerOf2_64(EnumVal))
551        PowerOfTwo = false;
552      else if (EnumVal > MaxPowerOfTwoVal)
553        MaxPowerOfTwoVal = EnumVal;
554    }
555  }
556  return PowerOfTwo && (MaxPowerOfTwoVal > 2);
557}
558
559void ObjCMigrateASTConsumer::migrateProtocolConformance(ASTContext &Ctx,
560                                            const ObjCImplementationDecl *ImpDecl) {
561  const ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface();
562  if (!IDecl || ObjCProtocolDecls.empty())
563    return;
564  // Find all implicit conforming protocols for this class
565  // and make them explicit.
566  llvm::SmallPtrSet<ObjCProtocolDecl *, 8> ExplicitProtocols;
567  Ctx.CollectInheritedProtocols(IDecl, ExplicitProtocols);
568  llvm::SmallVector<ObjCProtocolDecl *, 8> PotentialImplicitProtocols;
569
570  for (llvm::SmallPtrSet<ObjCProtocolDecl*, 32>::iterator I =
571       ObjCProtocolDecls.begin(),
572       E = ObjCProtocolDecls.end(); I != E; ++I)
573    if (!ExplicitProtocols.count(*I))
574      PotentialImplicitProtocols.push_back(*I);
575
576  if (PotentialImplicitProtocols.empty())
577    return;
578
579  // go through list of non-optional methods and properties in each protocol
580  // in the PotentialImplicitProtocols list. If class implements every one of the
581  // methods and properties, then this class conforms to this protocol.
582  llvm::SmallVector<ObjCProtocolDecl*, 8> ConformingProtocols;
583  for (unsigned i = 0, e = PotentialImplicitProtocols.size(); i != e; i++)
584    if (ClassImplementsAllMethodsAndProperties(Ctx, ImpDecl, IDecl,
585                                              PotentialImplicitProtocols[i]))
586      ConformingProtocols.push_back(PotentialImplicitProtocols[i]);
587
588  if (ConformingProtocols.empty())
589    return;
590
591  // Further reduce number of conforming protocols. If protocol P1 is in the list
592  // protocol P2 (P2<P1>), No need to include P1.
593  llvm::SmallVector<ObjCProtocolDecl*, 8> MinimalConformingProtocols;
594  for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
595    bool DropIt = false;
596    ObjCProtocolDecl *TargetPDecl = ConformingProtocols[i];
597    for (unsigned i1 = 0, e1 = ConformingProtocols.size(); i1 != e1; i1++) {
598      ObjCProtocolDecl *PDecl = ConformingProtocols[i1];
599      if (PDecl == TargetPDecl)
600        continue;
601      if (PDecl->lookupProtocolNamed(
602            TargetPDecl->getDeclName().getAsIdentifierInfo())) {
603        DropIt = true;
604        break;
605      }
606    }
607    if (!DropIt)
608      MinimalConformingProtocols.push_back(TargetPDecl);
609  }
610  edit::Commit commit(*Editor);
611  rewriteToObjCInterfaceDecl(IDecl, MinimalConformingProtocols,
612                             *NSAPIObj, commit);
613  Editor->commit(commit);
614}
615
616void ObjCMigrateASTConsumer::migrateNSEnumDecl(ASTContext &Ctx,
617                                           const EnumDecl *EnumDcl,
618                                           const TypedefDecl *TypedefDcl) {
619  if (!EnumDcl->isCompleteDefinition() || EnumDcl->getIdentifier() ||
620      !TypedefDcl->getIdentifier())
621    return;
622
623  QualType qt = TypedefDcl->getTypeSourceInfo()->getType();
624  bool IsNSIntegerType = NSAPIObj->isObjCNSIntegerType(qt);
625  bool IsNSUIntegerType = !IsNSIntegerType && NSAPIObj->isObjCNSUIntegerType(qt);
626
627  if (!IsNSIntegerType && !IsNSUIntegerType) {
628    // Also check for typedef enum {...} TD;
629    if (const EnumType *EnumTy = qt->getAs<EnumType>()) {
630      if (EnumTy->getDecl() == EnumDcl) {
631        bool NSOptions = UseNSOptionsMacro(Ctx, EnumDcl);
632        if (NSOptions) {
633          if (!Ctx.Idents.get("NS_OPTIONS").hasMacroDefinition())
634            return;
635        }
636        else if (!Ctx.Idents.get("NS_ENUM").hasMacroDefinition())
637          return;
638        edit::Commit commit(*Editor);
639        rewriteToNSMacroDecl(EnumDcl, TypedefDcl, *NSAPIObj, commit, !NSOptions);
640        Editor->commit(commit);
641      }
642    }
643    return;
644  }
645  if (IsNSIntegerType && UseNSOptionsMacro(Ctx, EnumDcl)) {
646    // We may still use NS_OPTIONS based on what we find in the enumertor list.
647    IsNSIntegerType = false;
648    IsNSUIntegerType = true;
649  }
650
651  // NS_ENUM must be available.
652  if (IsNSIntegerType && !Ctx.Idents.get("NS_ENUM").hasMacroDefinition())
653    return;
654  // NS_OPTIONS must be available.
655  if (IsNSUIntegerType && !Ctx.Idents.get("NS_OPTIONS").hasMacroDefinition())
656    return;
657  edit::Commit commit(*Editor);
658  rewriteToNSEnumDecl(EnumDcl, TypedefDcl, *NSAPIObj, commit, IsNSIntegerType);
659  Editor->commit(commit);
660}
661
662static void ReplaceWithInstancetype(const ObjCMigrateASTConsumer &ASTC,
663                                    ObjCMethodDecl *OM) {
664  SourceRange R;
665  std::string ClassString;
666  if (TypeSourceInfo *TSInfo =  OM->getResultTypeSourceInfo()) {
667    TypeLoc TL = TSInfo->getTypeLoc();
668    R = SourceRange(TL.getBeginLoc(), TL.getEndLoc());
669    ClassString = "instancetype";
670  }
671  else {
672    R = SourceRange(OM->getLocStart(), OM->getLocStart());
673    ClassString = OM->isInstanceMethod() ? '-' : '+';
674    ClassString += " (instancetype)";
675  }
676  edit::Commit commit(*ASTC.Editor);
677  commit.replace(R, ClassString);
678  ASTC.Editor->commit(commit);
679}
680
681void ObjCMigrateASTConsumer::migrateMethodInstanceType(ASTContext &Ctx,
682                                                       ObjCContainerDecl *CDecl,
683                                                       ObjCMethodDecl *OM) {
684  // bail out early and do not suggest 'instancetype' when the method already
685  // has a related result type,
686  if (OM->hasRelatedResultType())
687    return;
688
689  ObjCInstanceTypeFamily OIT_Family =
690    Selector::getInstTypeMethodFamily(OM->getSelector());
691
692  std::string ClassName;
693  switch (OIT_Family) {
694    case OIT_None:
695      migrateFactoryMethod(Ctx, CDecl, OM);
696      return;
697    case OIT_Array:
698      ClassName = "NSArray";
699      break;
700    case OIT_Dictionary:
701      ClassName = "NSDictionary";
702      break;
703    case OIT_Singleton:
704      migrateFactoryMethod(Ctx, CDecl, OM, OIT_Singleton);
705      return;
706  }
707  if (!OM->getResultType()->isObjCIdType())
708    return;
709
710  ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl);
711  if (!IDecl) {
712    if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl))
713      IDecl = CatDecl->getClassInterface();
714    else if (ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(CDecl))
715      IDecl = ImpDecl->getClassInterface();
716  }
717  if (!IDecl ||
718      !IDecl->lookupInheritedClass(&Ctx.Idents.get(ClassName))) {
719    migrateFactoryMethod(Ctx, CDecl, OM);
720    return;
721  }
722  ReplaceWithInstancetype(*this, OM);
723}
724
725void ObjCMigrateASTConsumer::migrateInstanceType(ASTContext &Ctx,
726                                                 ObjCContainerDecl *CDecl) {
727  // migrate methods which can have instancetype as their result type.
728  for (ObjCContainerDecl::method_iterator M = CDecl->meth_begin(),
729       MEnd = CDecl->meth_end();
730       M != MEnd; ++M) {
731    ObjCMethodDecl *Method = (*M);
732    migrateMethodInstanceType(Ctx, CDecl, Method);
733  }
734}
735
736void ObjCMigrateASTConsumer::migrateFactoryMethod(ASTContext &Ctx,
737                                                  ObjCContainerDecl *CDecl,
738                                                  ObjCMethodDecl *OM,
739                                                  ObjCInstanceTypeFamily OIT_Family) {
740  if (OM->isInstanceMethod() ||
741      OM->getResultType() == Ctx.getObjCInstanceType() ||
742      !OM->getResultType()->isObjCIdType())
743    return;
744
745  // Candidate factory methods are + (id) NaMeXXX : ... which belong to a class
746  // NSYYYNamE with matching names be at least 3 characters long.
747  ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl);
748  if (!IDecl) {
749    if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl))
750      IDecl = CatDecl->getClassInterface();
751    else if (ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(CDecl))
752      IDecl = ImpDecl->getClassInterface();
753  }
754  if (!IDecl)
755    return;
756
757  std::string StringClassName = IDecl->getName();
758  StringRef LoweredClassName(StringClassName);
759  std::string StringLoweredClassName = LoweredClassName.lower();
760  LoweredClassName = StringLoweredClassName;
761
762  IdentifierInfo *MethodIdName = OM->getSelector().getIdentifierInfoForSlot(0);
763  // Handle method with no name at its first selector slot; e.g. + (id):(int)x.
764  if (!MethodIdName)
765    return;
766
767  std::string MethodName = MethodIdName->getName();
768  if (OIT_Family == OIT_Singleton) {
769    StringRef STRefMethodName(MethodName);
770    size_t len = 0;
771    if (STRefMethodName.startswith("standard"))
772      len = strlen("standard");
773    else if (STRefMethodName.startswith("shared"))
774      len = strlen("shared");
775    else if (STRefMethodName.startswith("default"))
776      len = strlen("default");
777    else
778      return;
779    MethodName = STRefMethodName.substr(len);
780  }
781  std::string MethodNameSubStr = MethodName.substr(0, 3);
782  StringRef MethodNamePrefix(MethodNameSubStr);
783  std::string StringLoweredMethodNamePrefix = MethodNamePrefix.lower();
784  MethodNamePrefix = StringLoweredMethodNamePrefix;
785  size_t Ix = LoweredClassName.rfind(MethodNamePrefix);
786  if (Ix == StringRef::npos)
787    return;
788  std::string ClassNamePostfix = LoweredClassName.substr(Ix);
789  StringRef LoweredMethodName(MethodName);
790  std::string StringLoweredMethodName = LoweredMethodName.lower();
791  LoweredMethodName = StringLoweredMethodName;
792  if (!LoweredMethodName.startswith(ClassNamePostfix))
793    return;
794  ReplaceWithInstancetype(*this, OM);
795}
796
797static bool IsVoidStarType(QualType Ty) {
798  if (!Ty->isPointerType())
799    return false;
800
801  while (const TypedefType *TD = dyn_cast<TypedefType>(Ty.getTypePtr()))
802    Ty = TD->getDecl()->getUnderlyingType();
803
804  // Is the type void*?
805  const PointerType* PT = Ty->getAs<PointerType>();
806  if (PT->getPointeeType().getUnqualifiedType()->isVoidType())
807    return true;
808  return IsVoidStarType(PT->getPointeeType());
809}
810
811/// AuditedType - This routine audits the type AT and returns false if it is one of known
812/// CF object types or of the "void *" variety. It returns true if we don't care about the type
813/// such as a non-pointer or pointers which have no ownership issues (such as "int *").
814static bool AuditedType (QualType AT) {
815  if (!AT->isAnyPointerType() && !AT->isBlockPointerType())
816    return true;
817  // FIXME. There isn't much we can say about CF pointer type; or is there?
818  if (ento::coreFoundation::isCFObjectRef(AT) ||
819      IsVoidStarType(AT) ||
820      // If an ObjC object is type, assuming that it is not a CF function and
821      // that it is an un-audited function.
822      AT->isObjCObjectPointerType() || AT->isObjCBuiltinType())
823    return false;
824  // All other pointers are assumed audited as harmless.
825  return true;
826}
827
828void ObjCMigrateASTConsumer::AnnotateImplicitBridging(ASTContext &Ctx) {
829  if (CFFunctionIBCandidates.empty())
830    return;
831  if (!Ctx.Idents.get("CF_IMPLICIT_BRIDGING_ENABLED").hasMacroDefinition()) {
832    CFFunctionIBCandidates.clear();
833    FileId = 0;
834    return;
835  }
836  // Insert CF_IMPLICIT_BRIDGING_ENABLE/CF_IMPLICIT_BRIDGING_DISABLED
837  const Decl *FirstFD = CFFunctionIBCandidates[0];
838  const Decl *LastFD  =
839    CFFunctionIBCandidates[CFFunctionIBCandidates.size()-1];
840  const char *PragmaString = "\nCF_IMPLICIT_BRIDGING_ENABLED\n\n";
841  edit::Commit commit(*Editor);
842  commit.insertBefore(FirstFD->getLocStart(), PragmaString);
843  PragmaString = "\n\nCF_IMPLICIT_BRIDGING_DISABLED\n";
844  SourceLocation EndLoc = LastFD->getLocEnd();
845  // get location just past end of function location.
846  EndLoc = PP.getLocForEndOfToken(EndLoc);
847  if (isa<FunctionDecl>(LastFD)) {
848    // For Methods, EndLoc points to the ending semcolon. So,
849    // not of these extra work is needed.
850    Token Tok;
851    // get locaiton of token that comes after end of function.
852    bool Failed = PP.getRawToken(EndLoc, Tok, /*IgnoreWhiteSpace=*/true);
853    if (!Failed)
854      EndLoc = Tok.getLocation();
855  }
856  commit.insertAfterToken(EndLoc, PragmaString);
857  Editor->commit(commit);
858  FileId = 0;
859  CFFunctionIBCandidates.clear();
860}
861
862void ObjCMigrateASTConsumer::migrateCFAnnotation(ASTContext &Ctx, const Decl *Decl) {
863  if (Decl->hasAttr<CFAuditedTransferAttr>()) {
864    assert(CFFunctionIBCandidates.empty() &&
865           "Cannot have audited functions/methods inside user "
866           "provided CF_IMPLICIT_BRIDGING_ENABLE");
867    return;
868  }
869
870  // Finction must be annotated first.
871  CF_BRIDGING_KIND AuditKind;
872  if (const FunctionDecl *FuncDecl = dyn_cast<FunctionDecl>(Decl))
873    AuditKind = migrateAddFunctionAnnotation(Ctx, FuncDecl);
874  else
875    AuditKind = migrateAddMethodAnnotation(Ctx, cast<ObjCMethodDecl>(Decl));
876  if (AuditKind == CF_BRIDGING_ENABLE) {
877    CFFunctionIBCandidates.push_back(Decl);
878    if (!FileId)
879      FileId = PP.getSourceManager().getFileID(Decl->getLocation()).getHashValue();
880  }
881  else if (AuditKind == CF_BRIDGING_MAY_INCLUDE) {
882    if (!CFFunctionIBCandidates.empty()) {
883      CFFunctionIBCandidates.push_back(Decl);
884      if (!FileId)
885        FileId = PP.getSourceManager().getFileID(Decl->getLocation()).getHashValue();
886    }
887  }
888  else
889    AnnotateImplicitBridging(Ctx);
890}
891
892void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
893                                              const CallEffects &CE,
894                                              const FunctionDecl *FuncDecl,
895                                              bool ResultAnnotated) {
896  // Annotate function.
897  if (!ResultAnnotated) {
898    RetEffect Ret = CE.getReturnValue();
899    const char *AnnotationString = 0;
900    if (Ret.getObjKind() == RetEffect::CF && Ret.isOwned()) {
901      if (Ctx.Idents.get("CF_RETURNS_RETAINED").hasMacroDefinition())
902        AnnotationString = " CF_RETURNS_RETAINED";
903    }
904    else if (Ret.getObjKind() == RetEffect::CF && !Ret.isOwned()) {
905      if (Ctx.Idents.get("CF_RETURNS_NOT_RETAINED").hasMacroDefinition())
906        AnnotationString = " CF_RETURNS_NOT_RETAINED";
907    }
908    if (AnnotationString) {
909      edit::Commit commit(*Editor);
910      commit.insertAfterToken(FuncDecl->getLocEnd(), AnnotationString);
911      Editor->commit(commit);
912    }
913  }
914  llvm::ArrayRef<ArgEffect> AEArgs = CE.getArgs();
915  unsigned i = 0;
916  for (FunctionDecl::param_const_iterator pi = FuncDecl->param_begin(),
917       pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) {
918    const ParmVarDecl *pd = *pi;
919    ArgEffect AE = AEArgs[i];
920    if (AE == DecRef && !pd->getAttr<CFConsumedAttr>() &&
921        Ctx.Idents.get("CF_CONSUMED").hasMacroDefinition()) {
922      edit::Commit commit(*Editor);
923      commit.insertBefore(pd->getLocation(), "CF_CONSUMED ");
924      Editor->commit(commit);
925    }
926  }
927}
928
929
930ObjCMigrateASTConsumer::CF_BRIDGING_KIND
931  ObjCMigrateASTConsumer::migrateAddFunctionAnnotation(
932                                                  ASTContext &Ctx,
933                                                  const FunctionDecl *FuncDecl) {
934  if (FuncDecl->hasBody())
935    return CF_BRIDGING_NONE;
936
937  CallEffects CE  = CallEffects::getEffect(FuncDecl);
938  bool FuncIsReturnAnnotated = (FuncDecl->getAttr<CFReturnsRetainedAttr>() ||
939                                FuncDecl->getAttr<CFReturnsNotRetainedAttr>());
940
941  // Trivial case of when funciton is annotated and has no argument.
942  if (FuncIsReturnAnnotated && FuncDecl->getNumParams() == 0)
943    return CF_BRIDGING_NONE;
944
945  bool ReturnCFAudited = false;
946  if (!FuncIsReturnAnnotated) {
947    RetEffect Ret = CE.getReturnValue();
948    if (Ret.getObjKind() == RetEffect::CF &&
949        (Ret.isOwned() || !Ret.isOwned()))
950      ReturnCFAudited = true;
951    else if (!AuditedType(FuncDecl->getResultType()))
952      return CF_BRIDGING_NONE;
953  }
954
955  // At this point result type is audited for potential inclusion.
956  // Now, how about argument types.
957  llvm::ArrayRef<ArgEffect> AEArgs = CE.getArgs();
958  unsigned i = 0;
959  bool ArgCFAudited = false;
960  for (FunctionDecl::param_const_iterator pi = FuncDecl->param_begin(),
961       pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) {
962    const ParmVarDecl *pd = *pi;
963    ArgEffect AE = AEArgs[i];
964    if (AE == DecRef /*CFConsumed annotated*/ || AE == IncRef) {
965      if (AE == DecRef && !pd->getAttr<CFConsumedAttr>())
966        ArgCFAudited = true;
967      else if (AE == IncRef)
968        ArgCFAudited = true;
969    }
970    else {
971      QualType AT = pd->getType();
972      if (!AuditedType(AT)) {
973        AddCFAnnotations(Ctx, CE, FuncDecl, FuncIsReturnAnnotated);
974        return CF_BRIDGING_NONE;
975      }
976    }
977  }
978  if (ReturnCFAudited || ArgCFAudited)
979    return CF_BRIDGING_ENABLE;
980
981  return CF_BRIDGING_MAY_INCLUDE;
982}
983
984void ObjCMigrateASTConsumer::migrateARCSafeAnnotation(ASTContext &Ctx,
985                                                 ObjCContainerDecl *CDecl) {
986  if (!isa<ObjCInterfaceDecl>(CDecl))
987    return;
988
989  // migrate methods which can have instancetype as their result type.
990  for (ObjCContainerDecl::method_iterator M = CDecl->meth_begin(),
991       MEnd = CDecl->meth_end();
992       M != MEnd; ++M) {
993    ObjCMethodDecl *Method = (*M);
994    migrateCFAnnotation(Ctx, Method);
995  }
996}
997
998void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
999                                              const CallEffects &CE,
1000                                              const ObjCMethodDecl *MethodDecl,
1001                                              bool ResultAnnotated) {
1002  // Annotate function.
1003  if (!ResultAnnotated) {
1004    RetEffect Ret = CE.getReturnValue();
1005    const char *AnnotationString = 0;
1006    if (Ret.getObjKind() == RetEffect::CF && Ret.isOwned()) {
1007      if (Ctx.Idents.get("CF_RETURNS_RETAINED").hasMacroDefinition())
1008        AnnotationString = " CF_RETURNS_RETAINED";
1009    }
1010    else if (Ret.getObjKind() == RetEffect::CF && !Ret.isOwned()) {
1011      if (Ctx.Idents.get("CF_RETURNS_NOT_RETAINED").hasMacroDefinition())
1012        AnnotationString = " CF_RETURNS_NOT_RETAINED";
1013    }
1014    if (AnnotationString) {
1015      edit::Commit commit(*Editor);
1016      commit.insertBefore(MethodDecl->getLocEnd(), AnnotationString);
1017      Editor->commit(commit);
1018    }
1019  }
1020  llvm::ArrayRef<ArgEffect> AEArgs = CE.getArgs();
1021  unsigned i = 0;
1022  for (ObjCMethodDecl::param_const_iterator pi = MethodDecl->param_begin(),
1023       pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) {
1024    const ParmVarDecl *pd = *pi;
1025    ArgEffect AE = AEArgs[i];
1026    if (AE == DecRef && !pd->getAttr<CFConsumedAttr>() &&
1027        Ctx.Idents.get("CF_CONSUMED").hasMacroDefinition()) {
1028      edit::Commit commit(*Editor);
1029      commit.insertBefore(pd->getLocation(), "CF_CONSUMED ");
1030      Editor->commit(commit);
1031    }
1032  }
1033}
1034
1035ObjCMigrateASTConsumer::CF_BRIDGING_KIND
1036  ObjCMigrateASTConsumer::migrateAddMethodAnnotation(
1037                                            ASTContext &Ctx,
1038                                            const ObjCMethodDecl *MethodDecl) {
1039  if (MethodDecl->hasBody())
1040    return CF_BRIDGING_NONE;
1041
1042  CallEffects CE  = CallEffects::getEffect(MethodDecl);
1043  bool MethodIsReturnAnnotated = (MethodDecl->getAttr<CFReturnsRetainedAttr>() ||
1044                                  MethodDecl->getAttr<CFReturnsNotRetainedAttr>());
1045
1046  // Trivial case of when funciton is annotated and has no argument.
1047  if (MethodIsReturnAnnotated &&
1048      (MethodDecl->param_begin() == MethodDecl->param_end()))
1049    return CF_BRIDGING_NONE;
1050
1051  bool ReturnCFAudited = false;
1052  if (!MethodIsReturnAnnotated) {
1053    RetEffect Ret = CE.getReturnValue();
1054    if (Ret.getObjKind() == RetEffect::CF && (Ret.isOwned() || !Ret.isOwned()))
1055      ReturnCFAudited = true;
1056    else if (!AuditedType(MethodDecl->getResultType()))
1057      return CF_BRIDGING_NONE;
1058  }
1059
1060  // At this point result type is either annotated or audited.
1061  // Now, how about argument types.
1062  llvm::ArrayRef<ArgEffect> AEArgs = CE.getArgs();
1063  unsigned i = 0;
1064  bool ArgCFAudited = false;
1065  for (ObjCMethodDecl::param_const_iterator pi = MethodDecl->param_begin(),
1066       pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) {
1067    const ParmVarDecl *pd = *pi;
1068    ArgEffect AE = AEArgs[i];
1069    if (AE == DecRef /*CFConsumed annotated*/ || AE == IncRef) {
1070      if (AE == DecRef && !pd->getAttr<CFConsumedAttr>())
1071        ArgCFAudited = true;
1072      else if (AE == IncRef)
1073        ArgCFAudited = true;
1074    }
1075    else {
1076      QualType AT = pd->getType();
1077      if (!AuditedType(AT)) {
1078        AddCFAnnotations(Ctx, CE, MethodDecl, MethodIsReturnAnnotated);
1079        return CF_BRIDGING_NONE;
1080      }
1081    }
1082  }
1083  if (ReturnCFAudited || ArgCFAudited)
1084    return CF_BRIDGING_ENABLE;
1085
1086  return CF_BRIDGING_MAY_INCLUDE;
1087}
1088
1089namespace {
1090
1091class RewritesReceiver : public edit::EditsReceiver {
1092  Rewriter &Rewrite;
1093
1094public:
1095  RewritesReceiver(Rewriter &Rewrite) : Rewrite(Rewrite) { }
1096
1097  virtual void insert(SourceLocation loc, StringRef text) {
1098    Rewrite.InsertText(loc, text);
1099  }
1100  virtual void replace(CharSourceRange range, StringRef text) {
1101    Rewrite.ReplaceText(range.getBegin(), Rewrite.getRangeSize(range), text);
1102  }
1103};
1104
1105}
1106
1107void ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) {
1108
1109  TranslationUnitDecl *TU = Ctx.getTranslationUnitDecl();
1110  if (MigrateProperty) {
1111    for (DeclContext::decl_iterator D = TU->decls_begin(), DEnd = TU->decls_end();
1112         D != DEnd; ++D) {
1113      if (unsigned FID =
1114            PP.getSourceManager().getFileID((*D)->getLocation()).getHashValue())
1115        if (FileId && FileId != FID) {
1116          assert(!CFFunctionIBCandidates.empty());
1117          AnnotateImplicitBridging(Ctx);
1118        }
1119
1120      if (ObjCInterfaceDecl *CDecl = dyn_cast<ObjCInterfaceDecl>(*D))
1121        migrateObjCInterfaceDecl(Ctx, CDecl);
1122      else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(*D))
1123        ObjCProtocolDecls.insert(PDecl);
1124      else if (const ObjCImplementationDecl *ImpDecl =
1125               dyn_cast<ObjCImplementationDecl>(*D))
1126        migrateProtocolConformance(Ctx, ImpDecl);
1127      else if (const EnumDecl *ED = dyn_cast<EnumDecl>(*D)) {
1128        DeclContext::decl_iterator N = D;
1129        ++N;
1130        if (N != DEnd)
1131          if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(*N))
1132            migrateNSEnumDecl(Ctx, ED, TD);
1133      }
1134      else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*D))
1135        migrateCFAnnotation(Ctx, FD);
1136
1137      if (ObjCContainerDecl *CDecl = dyn_cast<ObjCContainerDecl>(*D)) {
1138        // migrate methods which can have instancetype as their result type.
1139        migrateInstanceType(Ctx, CDecl);
1140        // annotate methods with CF annotations.
1141        migrateARCSafeAnnotation(Ctx, CDecl);
1142      }
1143    }
1144    AnnotateImplicitBridging(Ctx);
1145  }
1146
1147  Rewriter rewriter(Ctx.getSourceManager(), Ctx.getLangOpts());
1148  RewritesReceiver Rec(rewriter);
1149  Editor->applyRewrites(Rec);
1150
1151  for (Rewriter::buffer_iterator
1152        I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) {
1153    FileID FID = I->first;
1154    RewriteBuffer &buf = I->second;
1155    const FileEntry *file = Ctx.getSourceManager().getFileEntryForID(FID);
1156    assert(file);
1157    SmallString<512> newText;
1158    llvm::raw_svector_ostream vecOS(newText);
1159    buf.write(vecOS);
1160    vecOS.flush();
1161    llvm::MemoryBuffer *memBuf = llvm::MemoryBuffer::getMemBufferCopy(
1162                   StringRef(newText.data(), newText.size()), file->getName());
1163    SmallString<64> filePath(file->getName());
1164    FileMgr.FixupRelativePath(filePath);
1165    Remapper.remap(filePath.str(), memBuf);
1166  }
1167
1168  if (IsOutputFile) {
1169    Remapper.flushToFile(MigrateDir, Ctx.getDiagnostics());
1170  } else {
1171    Remapper.flushToDisk(MigrateDir, Ctx.getDiagnostics());
1172  }
1173}
1174
1175bool MigrateSourceAction::BeginInvocation(CompilerInstance &CI) {
1176  CI.getDiagnostics().setIgnoreAllWarnings(true);
1177  return true;
1178}
1179
1180ASTConsumer *MigrateSourceAction::CreateASTConsumer(CompilerInstance &CI,
1181                                                  StringRef InFile) {
1182  PPConditionalDirectiveRecord *
1183    PPRec = new PPConditionalDirectiveRecord(CI.getSourceManager());
1184  CI.getPreprocessor().addPPCallbacks(PPRec);
1185  return new ObjCMigrateASTConsumer(CI.getFrontendOpts().OutputFile,
1186                                    /*MigrateLiterals=*/true,
1187                                    /*MigrateSubscripting=*/true,
1188                                    /*MigrateProperty*/true,
1189                                    /*MigrateReadonlyProperty*/true,
1190                                    Remapper,
1191                                    CI.getFileManager(),
1192                                    PPRec,
1193                                    CI.getPreprocessor(),
1194                                    /*isOutputFile=*/true);
1195}
1196