clang  8.0.0svn
ObjCMT.cpp
Go to the documentation of this file.
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/ARCMT.h"
13 #include "clang/AST/ASTConsumer.h"
14 #include "clang/AST/ASTContext.h"
15 #include "clang/AST/Attr.h"
16 #include "clang/AST/NSAPI.h"
17 #include "clang/AST/ParentMap.h"
21 #include "clang/Edit/Commit.h"
24 #include "clang/Edit/Rewriters.h"
28 #include "clang/Lex/Preprocessor.h"
31 #include "llvm/ADT/SmallString.h"
32 #include "llvm/ADT/StringSet.h"
33 #include "llvm/Support/Path.h"
34 #include "llvm/Support/SourceMgr.h"
35 #include "llvm/Support/YAMLParser.h"
36 
37 using namespace clang;
38 using namespace arcmt;
39 using namespace ento;
40 
41 namespace {
42 
43 class ObjCMigrateASTConsumer : public ASTConsumer {
44  enum CF_BRIDGING_KIND {
45  CF_BRIDGING_NONE,
46  CF_BRIDGING_ENABLE,
47  CF_BRIDGING_MAY_INCLUDE
48  };
49 
50  void migrateDecl(Decl *D);
51  void migrateObjCContainerDecl(ASTContext &Ctx, ObjCContainerDecl *D);
52  void migrateProtocolConformance(ASTContext &Ctx,
53  const ObjCImplementationDecl *ImpDecl);
54  void CacheObjCNSIntegerTypedefed(const TypedefDecl *TypedefDcl);
55  bool migrateNSEnumDecl(ASTContext &Ctx, const EnumDecl *EnumDcl,
56  const TypedefDecl *TypedefDcl);
57  void migrateAllMethodInstaceType(ASTContext &Ctx, ObjCContainerDecl *CDecl);
58  void migrateMethodInstanceType(ASTContext &Ctx, ObjCContainerDecl *CDecl,
59  ObjCMethodDecl *OM);
60  bool migrateProperty(ASTContext &Ctx, ObjCContainerDecl *D, ObjCMethodDecl *OM);
61  void migrateNsReturnsInnerPointer(ASTContext &Ctx, ObjCMethodDecl *OM);
62  void migratePropertyNsReturnsInnerPointer(ASTContext &Ctx, ObjCPropertyDecl *P);
63  void migrateFactoryMethod(ASTContext &Ctx, ObjCContainerDecl *CDecl,
64  ObjCMethodDecl *OM,
65  ObjCInstanceTypeFamily OIT_Family = OIT_None);
66 
67  void migrateCFAnnotation(ASTContext &Ctx, const Decl *Decl);
68  void AddCFAnnotations(ASTContext &Ctx, const CallEffects &CE,
69  const FunctionDecl *FuncDecl, bool ResultAnnotated);
70  void AddCFAnnotations(ASTContext &Ctx, const CallEffects &CE,
71  const ObjCMethodDecl *MethodDecl, bool ResultAnnotated);
72 
73  void AnnotateImplicitBridging(ASTContext &Ctx);
74 
75  CF_BRIDGING_KIND migrateAddFunctionAnnotation(ASTContext &Ctx,
76  const FunctionDecl *FuncDecl);
77 
78  void migrateARCSafeAnnotation(ASTContext &Ctx, ObjCContainerDecl *CDecl);
79 
80  void migrateAddMethodAnnotation(ASTContext &Ctx,
81  const ObjCMethodDecl *MethodDecl);
82 
83  void inferDesignatedInitializers(ASTContext &Ctx,
84  const ObjCImplementationDecl *ImplD);
85 
86  bool InsertFoundation(ASTContext &Ctx, SourceLocation Loc);
87 
88 public:
89  std::string MigrateDir;
90  unsigned ASTMigrateActions;
91  FileID FileId;
92  const TypedefDecl *NSIntegerTypedefed;
93  const TypedefDecl *NSUIntegerTypedefed;
94  std::unique_ptr<NSAPI> NSAPIObj;
95  std::unique_ptr<edit::EditedSource> Editor;
96  FileRemapper &Remapper;
97  FileManager &FileMgr;
98  const PPConditionalDirectiveRecord *PPRec;
99  Preprocessor &PP;
100  bool IsOutputFile;
101  bool FoundationIncluded;
102  llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ObjCProtocolDecls;
103  llvm::SmallVector<const Decl *, 8> CFFunctionIBCandidates;
104  llvm::StringSet<> WhiteListFilenames;
105 
106  ObjCMigrateASTConsumer(StringRef migrateDir,
107  unsigned astMigrateActions,
108  FileRemapper &remapper,
109  FileManager &fileMgr,
110  const PPConditionalDirectiveRecord *PPRec,
111  Preprocessor &PP,
112  bool isOutputFile,
113  ArrayRef<std::string> WhiteList)
114  : MigrateDir(migrateDir),
115  ASTMigrateActions(astMigrateActions),
116  NSIntegerTypedefed(nullptr), NSUIntegerTypedefed(nullptr),
117  Remapper(remapper), FileMgr(fileMgr), PPRec(PPRec), PP(PP),
118  IsOutputFile(isOutputFile),
119  FoundationIncluded(false){
120 
121  // FIXME: StringSet should have insert(iter, iter) to use here.
122  for (const std::string &Val : WhiteList)
123  WhiteListFilenames.insert(Val);
124  }
125 
126 protected:
127  void Initialize(ASTContext &Context) override {
128  NSAPIObj.reset(new NSAPI(Context));
129  Editor.reset(new edit::EditedSource(Context.getSourceManager(),
130  Context.getLangOpts(),
131  PPRec));
132  }
133 
134  bool HandleTopLevelDecl(DeclGroupRef DG) override {
135  for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
136  migrateDecl(*I);
137  return true;
138  }
139  void HandleInterestingDecl(DeclGroupRef DG) override {
140  // Ignore decls from the PCH.
141  }
142  void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) override {
143  ObjCMigrateASTConsumer::HandleTopLevelDecl(DG);
144  }
145 
146  void HandleTranslationUnit(ASTContext &Ctx) override;
147 
148  bool canModifyFile(StringRef Path) {
149  if (WhiteListFilenames.empty())
150  return true;
151  return WhiteListFilenames.find(llvm::sys::path::filename(Path))
152  != WhiteListFilenames.end();
153  }
154  bool canModifyFile(const FileEntry *FE) {
155  if (!FE)
156  return false;
157  return canModifyFile(FE->getName());
158  }
159  bool canModifyFile(FileID FID) {
160  if (FID.isInvalid())
161  return false;
162  return canModifyFile(PP.getSourceManager().getFileEntryForID(FID));
163  }
164 
165  bool canModify(const Decl *D) {
166  if (!D)
167  return false;
168  if (const ObjCCategoryImplDecl *CatImpl = dyn_cast<ObjCCategoryImplDecl>(D))
169  return canModify(CatImpl->getCategoryDecl());
170  if (const ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D))
171  return canModify(Impl->getClassInterface());
172  if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
173  return canModify(cast<Decl>(MD->getDeclContext()));
174 
175  FileID FID = PP.getSourceManager().getFileID(D->getLocation());
176  return canModifyFile(FID);
177  }
178 };
179 
180 } // end anonymous namespace
181 
183  std::unique_ptr<FrontendAction> WrappedAction,
184  StringRef migrateDir,
185  unsigned migrateAction)
186  : WrapperFrontendAction(std::move(WrappedAction)), MigrateDir(migrateDir),
187  ObjCMigAction(migrateAction),
188  CompInst(nullptr) {
189  if (MigrateDir.empty())
190  MigrateDir = "."; // user current directory if none is given.
191 }
192 
193 std::unique_ptr<ASTConsumer>
196  PPRec = new PPConditionalDirectiveRecord(CompInst->getSourceManager());
197  CI.getPreprocessor().addPPCallbacks(std::unique_ptr<PPCallbacks>(PPRec));
198  std::vector<std::unique_ptr<ASTConsumer>> Consumers;
199  Consumers.push_back(WrapperFrontendAction::CreateASTConsumer(CI, InFile));
200  Consumers.push_back(llvm::make_unique<ObjCMigrateASTConsumer>(
201  MigrateDir, ObjCMigAction, Remapper, CompInst->getFileManager(), PPRec,
202  CompInst->getPreprocessor(), false, None));
203  return llvm::make_unique<MultiplexConsumer>(std::move(Consumers));
204 }
205 
207  Remapper.initFromDisk(MigrateDir, CI.getDiagnostics(),
208  /*ignoreIfFilesChanges=*/true);
209  CompInst = &CI;
211  return true;
212 }
213 
214 namespace {
215  // FIXME. This duplicates one in RewriteObjCFoundationAPI.cpp
217  const Expr* Expr = FullExpr->IgnoreImpCasts();
218  return !(isa<ArraySubscriptExpr>(Expr) || isa<CallExpr>(Expr) ||
219  isa<DeclRefExpr>(Expr) || isa<CXXNamedCastExpr>(Expr) ||
220  isa<CXXConstructExpr>(Expr) || isa<CXXThisExpr>(Expr) ||
221  isa<CXXTypeidExpr>(Expr) ||
222  isa<CXXUnresolvedConstructExpr>(Expr) ||
223  isa<ObjCMessageExpr>(Expr) || isa<ObjCPropertyRefExpr>(Expr) ||
224  isa<ObjCProtocolExpr>(Expr) || isa<MemberExpr>(Expr) ||
225  isa<ObjCIvarRefExpr>(Expr) || isa<ParenExpr>(FullExpr) ||
226  isa<ParenListExpr>(Expr) || isa<SizeOfPackExpr>(Expr));
227  }
228 
229  /// - Rewrite message expression for Objective-C setter and getters into
230  /// property-dot syntax.
231  bool rewriteToPropertyDotSyntax(const ObjCMessageExpr *Msg,
232  Preprocessor &PP,
233  const NSAPI &NS, edit::Commit &commit,
234  const ParentMap *PMap) {
235  if (!Msg || Msg->isImplicit() ||
238  return false;
239  if (const Expr *Receiver = Msg->getInstanceReceiver())
240  if (Receiver->getType()->isObjCBuiltinType())
241  return false;
242 
243  const ObjCMethodDecl *Method = Msg->getMethodDecl();
244  if (!Method)
245  return false;
246  if (!Method->isPropertyAccessor())
247  return false;
248 
249  const ObjCPropertyDecl *Prop = Method->findPropertyDecl();
250  if (!Prop)
251  return false;
252 
253  SourceRange MsgRange = Msg->getSourceRange();
254  bool ReceiverIsSuper =
256  // for 'super' receiver is nullptr.
257  const Expr *receiver = Msg->getInstanceReceiver();
258  bool NeedsParen =
259  ReceiverIsSuper ? false : subscriptOperatorNeedsParens(receiver);
260  bool IsGetter = (Msg->getNumArgs() == 0);
261  if (IsGetter) {
262  // Find space location range between receiver expression and getter method.
263  SourceLocation BegLoc =
264  ReceiverIsSuper ? Msg->getSuperLoc() : receiver->getEndLoc();
265  BegLoc = PP.getLocForEndOfToken(BegLoc);
266  SourceLocation EndLoc = Msg->getSelectorLoc(0);
267  SourceRange SpaceRange(BegLoc, EndLoc);
268  std::string PropertyDotString;
269  // rewrite getter method expression into: receiver.property or
270  // (receiver).property
271  if (NeedsParen) {
272  commit.insertBefore(receiver->getBeginLoc(), "(");
273  PropertyDotString = ").";
274  }
275  else
276  PropertyDotString = ".";
277  PropertyDotString += Prop->getName();
278  commit.replace(SpaceRange, PropertyDotString);
279 
280  // remove '[' ']'
281  commit.replace(SourceRange(MsgRange.getBegin(), MsgRange.getBegin()), "");
282  commit.replace(SourceRange(MsgRange.getEnd(), MsgRange.getEnd()), "");
283  } else {
284  if (NeedsParen)
285  commit.insertWrap("(", receiver->getSourceRange(), ")");
286  std::string PropertyDotString = ".";
287  PropertyDotString += Prop->getName();
288  PropertyDotString += " =";
289  const Expr*const* Args = Msg->getArgs();
290  const Expr *RHS = Args[0];
291  if (!RHS)
292  return false;
293  SourceLocation BegLoc =
294  ReceiverIsSuper ? Msg->getSuperLoc() : receiver->getEndLoc();
295  BegLoc = PP.getLocForEndOfToken(BegLoc);
296  SourceLocation EndLoc = RHS->getBeginLoc();
297  EndLoc = EndLoc.getLocWithOffset(-1);
298  const char *colon = PP.getSourceManager().getCharacterData(EndLoc);
299  // Add a space after '=' if there is no space between RHS and '='
300  if (colon && colon[0] == ':')
301  PropertyDotString += " ";
302  SourceRange Range(BegLoc, EndLoc);
303  commit.replace(Range, PropertyDotString);
304  // remove '[' ']'
305  commit.replace(SourceRange(MsgRange.getBegin(), MsgRange.getBegin()), "");
306  commit.replace(SourceRange(MsgRange.getEnd(), MsgRange.getEnd()), "");
307  }
308  return true;
309  }
310 
311 class ObjCMigrator : public RecursiveASTVisitor<ObjCMigrator> {
312  ObjCMigrateASTConsumer &Consumer;
313  ParentMap &PMap;
314 
315 public:
316  ObjCMigrator(ObjCMigrateASTConsumer &consumer, ParentMap &PMap)
317  : Consumer(consumer), PMap(PMap) { }
318 
319  bool shouldVisitTemplateInstantiations() const { return false; }
320  bool shouldWalkTypesOfTypeLocs() const { return false; }
321 
322  bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
323  if (Consumer.ASTMigrateActions & FrontendOptions::ObjCMT_Literals) {
324  edit::Commit commit(*Consumer.Editor);
325  edit::rewriteToObjCLiteralSyntax(E, *Consumer.NSAPIObj, commit, &PMap);
326  Consumer.Editor->commit(commit);
327  }
328 
329  if (Consumer.ASTMigrateActions & FrontendOptions::ObjCMT_Subscripting) {
330  edit::Commit commit(*Consumer.Editor);
331  edit::rewriteToObjCSubscriptSyntax(E, *Consumer.NSAPIObj, commit);
332  Consumer.Editor->commit(commit);
333  }
334 
335  if (Consumer.ASTMigrateActions & FrontendOptions::ObjCMT_PropertyDotSyntax) {
336  edit::Commit commit(*Consumer.Editor);
337  rewriteToPropertyDotSyntax(E, Consumer.PP, *Consumer.NSAPIObj,
338  commit, &PMap);
339  Consumer.Editor->commit(commit);
340  }
341 
342  return true;
343  }
344 
345  bool TraverseObjCMessageExpr(ObjCMessageExpr *E) {
346  // Do depth first; we want to rewrite the subexpressions first so that if
347  // we have to move expressions we will move them already rewritten.
348  for (Stmt *SubStmt : E->children())
349  if (!TraverseStmt(SubStmt))
350  return false;
351 
352  return WalkUpFromObjCMessageExpr(E);
353  }
354 };
355 
356 class BodyMigrator : public RecursiveASTVisitor<BodyMigrator> {
357  ObjCMigrateASTConsumer &Consumer;
358  std::unique_ptr<ParentMap> PMap;
359 
360 public:
361  BodyMigrator(ObjCMigrateASTConsumer &consumer) : Consumer(consumer) { }
362 
363  bool shouldVisitTemplateInstantiations() const { return false; }
364  bool shouldWalkTypesOfTypeLocs() const { return false; }
365 
366  bool TraverseStmt(Stmt *S) {
367  PMap.reset(new ParentMap(S));
368  ObjCMigrator(Consumer, *PMap).TraverseStmt(S);
369  return true;
370  }
371 };
372 } // end anonymous namespace
373 
374 void ObjCMigrateASTConsumer::migrateDecl(Decl *D) {
375  if (!D)
376  return;
377  if (isa<ObjCMethodDecl>(D))
378  return; // Wait for the ObjC container declaration.
379 
380  BodyMigrator(*this).TraverseDecl(D);
381 }
382 
383 static void append_attr(std::string &PropertyString, const char *attr,
384  bool &LParenAdded) {
385  if (!LParenAdded) {
386  PropertyString += "(";
387  LParenAdded = true;
388  }
389  else
390  PropertyString += ", ";
391  PropertyString += attr;
392 }
393 
394 static
395 void MigrateBlockOrFunctionPointerTypeVariable(std::string & PropertyString,
396  const std::string& TypeString,
397  const char *name) {
398  const char *argPtr = TypeString.c_str();
399  int paren = 0;
400  while (*argPtr) {
401  switch (*argPtr) {
402  case '(':
403  PropertyString += *argPtr;
404  paren++;
405  break;
406  case ')':
407  PropertyString += *argPtr;
408  paren--;
409  break;
410  case '^':
411  case '*':
412  PropertyString += (*argPtr);
413  if (paren == 1) {
414  PropertyString += name;
415  name = "";
416  }
417  break;
418  default:
419  PropertyString += *argPtr;
420  break;
421  }
422  argPtr++;
423  }
424 }
425 
426 static const char *PropertyMemoryAttribute(ASTContext &Context, QualType ArgType) {
427  Qualifiers::ObjCLifetime propertyLifetime = ArgType.getObjCLifetime();
428  bool RetainableObject = ArgType->isObjCRetainableType();
429  if (RetainableObject &&
430  (propertyLifetime == Qualifiers::OCL_Strong
431  || propertyLifetime == Qualifiers::OCL_None)) {
432  if (const ObjCObjectPointerType *ObjPtrTy =
433  ArgType->getAs<ObjCObjectPointerType>()) {
434  ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface();
435  if (IDecl &&
436  IDecl->lookupNestedProtocol(&Context.Idents.get("NSCopying")))
437  return "copy";
438  else
439  return "strong";
440  }
441  else if (ArgType->isBlockPointerType())
442  return "copy";
443  } else if (propertyLifetime == Qualifiers::OCL_Weak)
444  // TODO. More precise determination of 'weak' attribute requires
445  // looking into setter's implementation for backing weak ivar.
446  return "weak";
447  else if (RetainableObject)
448  return ArgType->isBlockPointerType() ? "copy" : "strong";
449  return nullptr;
450 }
451 
452 static void rewriteToObjCProperty(const ObjCMethodDecl *Getter,
453  const ObjCMethodDecl *Setter,
454  const NSAPI &NS, edit::Commit &commit,
455  unsigned LengthOfPrefix,
456  bool Atomic, bool UseNsIosOnlyMacro,
457  bool AvailabilityArgsMatch) {
458  ASTContext &Context = NS.getASTContext();
459  bool LParenAdded = false;
460  std::string PropertyString = "@property ";
461  if (UseNsIosOnlyMacro && NS.isMacroDefined("NS_NONATOMIC_IOSONLY")) {
462  PropertyString += "(NS_NONATOMIC_IOSONLY";
463  LParenAdded = true;
464  } else if (!Atomic) {
465  PropertyString += "(nonatomic";
466  LParenAdded = true;
467  }
468 
469  std::string PropertyNameString = Getter->getNameAsString();
470  StringRef PropertyName(PropertyNameString);
471  if (LengthOfPrefix > 0) {
472  if (!LParenAdded) {
473  PropertyString += "(getter=";
474  LParenAdded = true;
475  }
476  else
477  PropertyString += ", getter=";
478  PropertyString += PropertyNameString;
479  }
480  // Property with no setter may be suggested as a 'readonly' property.
481  if (!Setter)
482  append_attr(PropertyString, "readonly", LParenAdded);
483 
484 
485  // Short circuit 'delegate' properties that contain the name "delegate" or
486  // "dataSource", or have exact name "target" to have 'assign' attribute.
487  if (PropertyName.equals("target") ||
488  (PropertyName.find("delegate") != StringRef::npos) ||
489  (PropertyName.find("dataSource") != StringRef::npos)) {
490  QualType QT = Getter->getReturnType();
491  if (!QT->isRealType())
492  append_attr(PropertyString, "assign", LParenAdded);
493  } else if (!Setter) {
494  QualType ResType = Context.getCanonicalType(Getter->getReturnType());
495  if (const char *MemoryManagementAttr = PropertyMemoryAttribute(Context, ResType))
496  append_attr(PropertyString, MemoryManagementAttr, LParenAdded);
497  } else {
498  const ParmVarDecl *argDecl = *Setter->param_begin();
499  QualType ArgType = Context.getCanonicalType(argDecl->getType());
500  if (const char *MemoryManagementAttr = PropertyMemoryAttribute(Context, ArgType))
501  append_attr(PropertyString, MemoryManagementAttr, LParenAdded);
502  }
503  if (LParenAdded)
504  PropertyString += ')';
505  QualType RT = Getter->getReturnType();
506  if (!isa<TypedefType>(RT)) {
507  // strip off any ARC lifetime qualifier.
508  QualType CanResultTy = Context.getCanonicalType(RT);
509  if (CanResultTy.getQualifiers().hasObjCLifetime()) {
510  Qualifiers Qs = CanResultTy.getQualifiers();
511  Qs.removeObjCLifetime();
512  RT = Context.getQualifiedType(CanResultTy.getUnqualifiedType(), Qs);
513  }
514  }
515  PropertyString += " ";
516  PrintingPolicy SubPolicy(Context.getPrintingPolicy());
517  SubPolicy.SuppressStrongLifetime = true;
518  SubPolicy.SuppressLifetimeQualifiers = true;
519  std::string TypeString = RT.getAsString(SubPolicy);
520  if (LengthOfPrefix > 0) {
521  // property name must strip off "is" and lower case the first character
522  // after that; e.g. isContinuous will become continuous.
523  StringRef PropertyNameStringRef(PropertyNameString);
524  PropertyNameStringRef = PropertyNameStringRef.drop_front(LengthOfPrefix);
525  PropertyNameString = PropertyNameStringRef;
526  bool NoLowering = (isUppercase(PropertyNameString[0]) &&
527  PropertyNameString.size() > 1 &&
528  isUppercase(PropertyNameString[1]));
529  if (!NoLowering)
530  PropertyNameString[0] = toLowercase(PropertyNameString[0]);
531  }
532  if (RT->isBlockPointerType() || RT->isFunctionPointerType())
534  TypeString,
535  PropertyNameString.c_str());
536  else {
537  char LastChar = TypeString[TypeString.size()-1];
538  PropertyString += TypeString;
539  if (LastChar != '*')
540  PropertyString += ' ';
541  PropertyString += PropertyNameString;
542  }
543  SourceLocation StartGetterSelectorLoc = Getter->getSelectorStartLoc();
544  Selector GetterSelector = Getter->getSelector();
545 
546  SourceLocation EndGetterSelectorLoc =
547  StartGetterSelectorLoc.getLocWithOffset(GetterSelector.getNameForSlot(0).size());
549  EndGetterSelectorLoc),
550  PropertyString);
551  if (Setter && AvailabilityArgsMatch) {
552  SourceLocation EndLoc = Setter->getDeclaratorEndLoc();
553  // Get location past ';'
554  EndLoc = EndLoc.getLocWithOffset(1);
555  SourceLocation BeginOfSetterDclLoc = Setter->getBeginLoc();
556  // FIXME. This assumes that setter decl; is immediately preceded by eoln.
557  // It is trying to remove the setter method decl. line entirely.
558  BeginOfSetterDclLoc = BeginOfSetterDclLoc.getLocWithOffset(-1);
559  commit.remove(SourceRange(BeginOfSetterDclLoc, EndLoc));
560  }
561 }
562 
564  if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(D)) {
565  StringRef Name = CatDecl->getName();
566  return Name.endswith("Deprecated");
567  }
568  return false;
569 }
570 
571 void ObjCMigrateASTConsumer::migrateObjCContainerDecl(ASTContext &Ctx,
572  ObjCContainerDecl *D) {
574  return;
575 
576  for (auto *Method : D->methods()) {
577  if (Method->isDeprecated())
578  continue;
579  bool PropertyInferred = migrateProperty(Ctx, D, Method);
580  // If a property is inferred, do not attempt to attach NS_RETURNS_INNER_POINTER to
581  // the getter method as it ends up on the property itself which we don't want
582  // to do unless -objcmt-returns-innerpointer-property option is on.
583  if (!PropertyInferred ||
585  if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation)
586  migrateNsReturnsInnerPointer(Ctx, Method);
587  }
588  if (!(ASTMigrateActions & FrontendOptions::ObjCMT_ReturnsInnerPointerProperty))
589  return;
590 
591  for (auto *Prop : D->instance_properties()) {
592  if ((ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) &&
593  !Prop->isDeprecated())
594  migratePropertyNsReturnsInnerPointer(Ctx, Prop);
595  }
596 }
597 
598 static bool
600  const ObjCImplementationDecl *ImpDecl,
601  const ObjCInterfaceDecl *IDecl,
602  ObjCProtocolDecl *Protocol) {
603  // In auto-synthesis, protocol properties are not synthesized. So,
604  // a conforming protocol must have its required properties declared
605  // in class interface.
606  bool HasAtleastOneRequiredProperty = false;
607  if (const ObjCProtocolDecl *PDecl = Protocol->getDefinition())
608  for (const auto *Property : PDecl->instance_properties()) {
609  if (Property->getPropertyImplementation() == ObjCPropertyDecl::Optional)
610  continue;
611  HasAtleastOneRequiredProperty = true;
612  DeclContext::lookup_result R = IDecl->lookup(Property->getDeclName());
613  if (R.size() == 0) {
614  // Relax the rule and look into class's implementation for a synthesize
615  // or dynamic declaration. Class is implementing a property coming from
616  // another protocol. This still makes the target protocol as conforming.
617  if (!ImpDecl->FindPropertyImplDecl(
618  Property->getDeclName().getAsIdentifierInfo(),
619  Property->getQueryKind()))
620  return false;
621  }
622  else if (ObjCPropertyDecl *ClassProperty = dyn_cast<ObjCPropertyDecl>(R[0])) {
623  if ((ClassProperty->getPropertyAttributes()
624  != Property->getPropertyAttributes()) ||
625  !Ctx.hasSameType(ClassProperty->getType(), Property->getType()))
626  return false;
627  }
628  else
629  return false;
630  }
631 
632  // At this point, all required properties in this protocol conform to those
633  // declared in the class.
634  // Check that class implements the required methods of the protocol too.
635  bool HasAtleastOneRequiredMethod = false;
636  if (const ObjCProtocolDecl *PDecl = Protocol->getDefinition()) {
637  if (PDecl->meth_begin() == PDecl->meth_end())
638  return HasAtleastOneRequiredProperty;
639  for (const auto *MD : PDecl->methods()) {
640  if (MD->isImplicit())
641  continue;
642  if (MD->getImplementationControl() == ObjCMethodDecl::Optional)
643  continue;
644  DeclContext::lookup_result R = ImpDecl->lookup(MD->getDeclName());
645  if (R.size() == 0)
646  return false;
647  bool match = false;
648  HasAtleastOneRequiredMethod = true;
649  for (unsigned I = 0, N = R.size(); I != N; ++I)
650  if (ObjCMethodDecl *ImpMD = dyn_cast<ObjCMethodDecl>(R[0]))
651  if (Ctx.ObjCMethodsAreEqual(MD, ImpMD)) {
652  match = true;
653  break;
654  }
655  if (!match)
656  return false;
657  }
658  }
659  return HasAtleastOneRequiredProperty || HasAtleastOneRequiredMethod;
660 }
661 
663  llvm::SmallVectorImpl<ObjCProtocolDecl*> &ConformingProtocols,
664  const NSAPI &NS, edit::Commit &commit) {
665  const ObjCList<ObjCProtocolDecl> &Protocols = IDecl->getReferencedProtocols();
666  std::string ClassString;
667  SourceLocation EndLoc =
668  IDecl->getSuperClass() ? IDecl->getSuperClassLoc() : IDecl->getLocation();
669 
670  if (Protocols.empty()) {
671  ClassString = '<';
672  for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
673  ClassString += ConformingProtocols[i]->getNameAsString();
674  if (i != (e-1))
675  ClassString += ", ";
676  }
677  ClassString += "> ";
678  }
679  else {
680  ClassString = ", ";
681  for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
682  ClassString += ConformingProtocols[i]->getNameAsString();
683  if (i != (e-1))
684  ClassString += ", ";
685  }
687  EndLoc = *PL;
688  }
689 
690  commit.insertAfterToken(EndLoc, ClassString);
691  return true;
692 }
693 
694 static StringRef GetUnsignedName(StringRef NSIntegerName) {
695  StringRef UnsignedName = llvm::StringSwitch<StringRef>(NSIntegerName)
696  .Case("int8_t", "uint8_t")
697  .Case("int16_t", "uint16_t")
698  .Case("int32_t", "uint32_t")
699  .Case("NSInteger", "NSUInteger")
700  .Case("int64_t", "uint64_t")
701  .Default(NSIntegerName);
702  return UnsignedName;
703 }
704 
705 static bool rewriteToNSEnumDecl(const EnumDecl *EnumDcl,
706  const TypedefDecl *TypedefDcl,
707  const NSAPI &NS, edit::Commit &commit,
708  StringRef NSIntegerName,
709  bool NSOptions) {
710  std::string ClassString;
711  if (NSOptions) {
712  ClassString = "typedef NS_OPTIONS(";
713  ClassString += GetUnsignedName(NSIntegerName);
714  }
715  else {
716  ClassString = "typedef NS_ENUM(";
717  ClassString += NSIntegerName;
718  }
719  ClassString += ", ";
720 
721  ClassString += TypedefDcl->getIdentifier()->getName();
722  ClassString += ')';
723  SourceRange R(EnumDcl->getBeginLoc(), EnumDcl->getBeginLoc());
724  commit.replace(R, ClassString);
725  SourceLocation EndOfEnumDclLoc = EnumDcl->getEndLoc();
726  EndOfEnumDclLoc = trans::findSemiAfterLocation(EndOfEnumDclLoc,
727  NS.getASTContext(), /*IsDecl*/true);
728  if (EndOfEnumDclLoc.isValid()) {
729  SourceRange EnumDclRange(EnumDcl->getBeginLoc(), EndOfEnumDclLoc);
730  commit.insertFromRange(TypedefDcl->getBeginLoc(), EnumDclRange);
731  }
732  else
733  return false;
734 
735  SourceLocation EndTypedefDclLoc = TypedefDcl->getEndLoc();
736  EndTypedefDclLoc = trans::findSemiAfterLocation(EndTypedefDclLoc,
737  NS.getASTContext(), /*IsDecl*/true);
738  if (EndTypedefDclLoc.isValid()) {
739  SourceRange TDRange(TypedefDcl->getBeginLoc(), EndTypedefDclLoc);
740  commit.remove(TDRange);
741  }
742  else
743  return false;
744 
745  EndOfEnumDclLoc =
747  /*IsDecl*/ true);
748  if (EndOfEnumDclLoc.isValid()) {
749  SourceLocation BeginOfEnumDclLoc = EnumDcl->getBeginLoc();
750  // FIXME. This assumes that enum decl; is immediately preceded by eoln.
751  // It is trying to remove the enum decl. lines entirely.
752  BeginOfEnumDclLoc = BeginOfEnumDclLoc.getLocWithOffset(-1);
753  commit.remove(SourceRange(BeginOfEnumDclLoc, EndOfEnumDclLoc));
754  return true;
755  }
756  return false;
757 }
758 
760  const EnumDecl *EnumDcl,
761  const TypedefDecl *TypedefDcl,
762  const NSAPI &NS, edit::Commit &commit,
763  bool IsNSIntegerType) {
764  QualType DesignatedEnumType = EnumDcl->getIntegerType();
765  assert(!DesignatedEnumType.isNull()
766  && "rewriteToNSMacroDecl - underlying enum type is null");
767 
768  PrintingPolicy Policy(Ctx.getPrintingPolicy());
769  std::string TypeString = DesignatedEnumType.getAsString(Policy);
770  std::string ClassString = IsNSIntegerType ? "NS_ENUM(" : "NS_OPTIONS(";
771  ClassString += TypeString;
772  ClassString += ", ";
773 
774  ClassString += TypedefDcl->getIdentifier()->getName();
775  ClassString += ") ";
776  SourceLocation EndLoc = EnumDcl->getBraceRange().getBegin();
777  if (EndLoc.isInvalid())
778  return;
779  CharSourceRange R =
780  CharSourceRange::getCharRange(EnumDcl->getBeginLoc(), EndLoc);
781  commit.replace(R, ClassString);
782  // This is to remove spaces between '}' and typedef name.
783  SourceLocation StartTypedefLoc = EnumDcl->getEndLoc();
784  StartTypedefLoc = StartTypedefLoc.getLocWithOffset(+1);
785  SourceLocation EndTypedefLoc = TypedefDcl->getEndLoc();
786 
787  commit.remove(SourceRange(StartTypedefLoc, EndTypedefLoc));
788 }
789 
791  const EnumDecl *EnumDcl) {
792  bool PowerOfTwo = true;
793  bool AllHexdecimalEnumerator = true;
794  uint64_t MaxPowerOfTwoVal = 0;
795  for (auto Enumerator : EnumDcl->enumerators()) {
796  const Expr *InitExpr = Enumerator->getInitExpr();
797  if (!InitExpr) {
798  PowerOfTwo = false;
799  AllHexdecimalEnumerator = false;
800  continue;
801  }
802  InitExpr = InitExpr->IgnoreParenCasts();
803  if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(InitExpr))
804  if (BO->isShiftOp() || BO->isBitwiseOp())
805  return true;
806 
807  uint64_t EnumVal = Enumerator->getInitVal().getZExtValue();
808  if (PowerOfTwo && EnumVal) {
809  if (!llvm::isPowerOf2_64(EnumVal))
810  PowerOfTwo = false;
811  else if (EnumVal > MaxPowerOfTwoVal)
812  MaxPowerOfTwoVal = EnumVal;
813  }
814  if (AllHexdecimalEnumerator && EnumVal) {
815  bool FoundHexdecimalEnumerator = false;
816  SourceLocation EndLoc = Enumerator->getEndLoc();
817  Token Tok;
818  if (!PP.getRawToken(EndLoc, Tok, /*IgnoreWhiteSpace=*/true))
819  if (Tok.isLiteral() && Tok.getLength() > 2) {
820  if (const char *StringLit = Tok.getLiteralData())
821  FoundHexdecimalEnumerator =
822  (StringLit[0] == '0' && (toLowercase(StringLit[1]) == 'x'));
823  }
824  if (!FoundHexdecimalEnumerator)
825  AllHexdecimalEnumerator = false;
826  }
827  }
828  return AllHexdecimalEnumerator || (PowerOfTwo && (MaxPowerOfTwoVal > 2));
829 }
830 
831 void ObjCMigrateASTConsumer::migrateProtocolConformance(ASTContext &Ctx,
832  const ObjCImplementationDecl *ImpDecl) {
833  const ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface();
834  if (!IDecl || ObjCProtocolDecls.empty() || IDecl->isDeprecated())
835  return;
836  // Find all implicit conforming protocols for this class
837  // and make them explicit.
838  llvm::SmallPtrSet<ObjCProtocolDecl *, 8> ExplicitProtocols;
839  Ctx.CollectInheritedProtocols(IDecl, ExplicitProtocols);
840  llvm::SmallVector<ObjCProtocolDecl *, 8> PotentialImplicitProtocols;
841 
842  for (ObjCProtocolDecl *ProtDecl : ObjCProtocolDecls)
843  if (!ExplicitProtocols.count(ProtDecl))
844  PotentialImplicitProtocols.push_back(ProtDecl);
845 
846  if (PotentialImplicitProtocols.empty())
847  return;
848 
849  // go through list of non-optional methods and properties in each protocol
850  // in the PotentialImplicitProtocols list. If class implements every one of the
851  // methods and properties, then this class conforms to this protocol.
852  llvm::SmallVector<ObjCProtocolDecl*, 8> ConformingProtocols;
853  for (unsigned i = 0, e = PotentialImplicitProtocols.size(); i != e; i++)
854  if (ClassImplementsAllMethodsAndProperties(Ctx, ImpDecl, IDecl,
855  PotentialImplicitProtocols[i]))
856  ConformingProtocols.push_back(PotentialImplicitProtocols[i]);
857 
858  if (ConformingProtocols.empty())
859  return;
860 
861  // Further reduce number of conforming protocols. If protocol P1 is in the list
862  // protocol P2 (P2<P1>), No need to include P1.
863  llvm::SmallVector<ObjCProtocolDecl*, 8> MinimalConformingProtocols;
864  for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
865  bool DropIt = false;
866  ObjCProtocolDecl *TargetPDecl = ConformingProtocols[i];
867  for (unsigned i1 = 0, e1 = ConformingProtocols.size(); i1 != e1; i1++) {
868  ObjCProtocolDecl *PDecl = ConformingProtocols[i1];
869  if (PDecl == TargetPDecl)
870  continue;
871  if (PDecl->lookupProtocolNamed(
872  TargetPDecl->getDeclName().getAsIdentifierInfo())) {
873  DropIt = true;
874  break;
875  }
876  }
877  if (!DropIt)
878  MinimalConformingProtocols.push_back(TargetPDecl);
879  }
880  if (MinimalConformingProtocols.empty())
881  return;
882  edit::Commit commit(*Editor);
883  rewriteToObjCInterfaceDecl(IDecl, MinimalConformingProtocols,
884  *NSAPIObj, commit);
885  Editor->commit(commit);
886 }
887 
888 void ObjCMigrateASTConsumer::CacheObjCNSIntegerTypedefed(
889  const TypedefDecl *TypedefDcl) {
890 
891  QualType qt = TypedefDcl->getTypeSourceInfo()->getType();
892  if (NSAPIObj->isObjCNSIntegerType(qt))
893  NSIntegerTypedefed = TypedefDcl;
894  else if (NSAPIObj->isObjCNSUIntegerType(qt))
895  NSUIntegerTypedefed = TypedefDcl;
896 }
897 
898 bool ObjCMigrateASTConsumer::migrateNSEnumDecl(ASTContext &Ctx,
899  const EnumDecl *EnumDcl,
900  const TypedefDecl *TypedefDcl) {
901  if (!EnumDcl->isCompleteDefinition() || EnumDcl->getIdentifier() ||
902  EnumDcl->isDeprecated())
903  return false;
904  if (!TypedefDcl) {
905  if (NSIntegerTypedefed) {
906  TypedefDcl = NSIntegerTypedefed;
907  NSIntegerTypedefed = nullptr;
908  }
909  else if (NSUIntegerTypedefed) {
910  TypedefDcl = NSUIntegerTypedefed;
911  NSUIntegerTypedefed = nullptr;
912  }
913  else
914  return false;
915  FileID FileIdOfTypedefDcl =
916  PP.getSourceManager().getFileID(TypedefDcl->getLocation());
917  FileID FileIdOfEnumDcl =
918  PP.getSourceManager().getFileID(EnumDcl->getLocation());
919  if (FileIdOfTypedefDcl != FileIdOfEnumDcl)
920  return false;
921  }
922  if (TypedefDcl->isDeprecated())
923  return false;
924 
925  QualType qt = TypedefDcl->getTypeSourceInfo()->getType();
926  StringRef NSIntegerName = NSAPIObj->GetNSIntegralKind(qt);
927 
928  if (NSIntegerName.empty()) {
929  // Also check for typedef enum {...} TD;
930  if (const EnumType *EnumTy = qt->getAs<EnumType>()) {
931  if (EnumTy->getDecl() == EnumDcl) {
932  bool NSOptions = UseNSOptionsMacro(PP, Ctx, EnumDcl);
933  if (!InsertFoundation(Ctx, TypedefDcl->getBeginLoc()))
934  return false;
935  edit::Commit commit(*Editor);
936  rewriteToNSMacroDecl(Ctx, EnumDcl, TypedefDcl, *NSAPIObj, commit, !NSOptions);
937  Editor->commit(commit);
938  return true;
939  }
940  }
941  return false;
942  }
943 
944  // We may still use NS_OPTIONS based on what we find in the enumertor list.
945  bool NSOptions = UseNSOptionsMacro(PP, Ctx, EnumDcl);
946  if (!InsertFoundation(Ctx, TypedefDcl->getBeginLoc()))
947  return false;
948  edit::Commit commit(*Editor);
949  bool Res = rewriteToNSEnumDecl(EnumDcl, TypedefDcl, *NSAPIObj,
950  commit, NSIntegerName, NSOptions);
951  Editor->commit(commit);
952  return Res;
953 }
954 
956  const ObjCMigrateASTConsumer &ASTC,
957  ObjCMethodDecl *OM) {
958  if (OM->getReturnType() == Ctx.getObjCInstanceType())
959  return; // already has instancetype.
960 
961  SourceRange R;
962  std::string ClassString;
963  if (TypeSourceInfo *TSInfo = OM->getReturnTypeSourceInfo()) {
964  TypeLoc TL = TSInfo->getTypeLoc();
965  R = SourceRange(TL.getBeginLoc(), TL.getEndLoc());
966  ClassString = "instancetype";
967  }
968  else {
969  R = SourceRange(OM->getBeginLoc(), OM->getBeginLoc());
970  ClassString = OM->isInstanceMethod() ? '-' : '+';
971  ClassString += " (instancetype)";
972  }
973  edit::Commit commit(*ASTC.Editor);
974  commit.replace(R, ClassString);
975  ASTC.Editor->commit(commit);
976 }
977 
978 static void ReplaceWithClasstype(const ObjCMigrateASTConsumer &ASTC,
979  ObjCMethodDecl *OM) {
980  ObjCInterfaceDecl *IDecl = OM->getClassInterface();
981  SourceRange R;
982  std::string ClassString;
983  if (TypeSourceInfo *TSInfo = OM->getReturnTypeSourceInfo()) {
984  TypeLoc TL = TSInfo->getTypeLoc();
985  R = SourceRange(TL.getBeginLoc(), TL.getEndLoc()); {
986  ClassString = IDecl->getName();
987  ClassString += "*";
988  }
989  }
990  else {
991  R = SourceRange(OM->getBeginLoc(), OM->getBeginLoc());
992  ClassString = "+ (";
993  ClassString += IDecl->getName(); ClassString += "*)";
994  }
995  edit::Commit commit(*ASTC.Editor);
996  commit.replace(R, ClassString);
997  ASTC.Editor->commit(commit);
998 }
999 
1000 void ObjCMigrateASTConsumer::migrateMethodInstanceType(ASTContext &Ctx,
1001  ObjCContainerDecl *CDecl,
1002  ObjCMethodDecl *OM) {
1003  ObjCInstanceTypeFamily OIT_Family =
1005 
1006  std::string ClassName;
1007  switch (OIT_Family) {
1008  case OIT_None:
1009  migrateFactoryMethod(Ctx, CDecl, OM);
1010  return;
1011  case OIT_Array:
1012  ClassName = "NSArray";
1013  break;
1014  case OIT_Dictionary:
1015  ClassName = "NSDictionary";
1016  break;
1017  case OIT_Singleton:
1018  migrateFactoryMethod(Ctx, CDecl, OM, OIT_Singleton);
1019  return;
1020  case OIT_Init:
1021  if (OM->getReturnType()->isObjCIdType())
1022  ReplaceWithInstancetype(Ctx, *this, OM);
1023  return;
1024  case OIT_ReturnsSelf:
1025  migrateFactoryMethod(Ctx, CDecl, OM, OIT_ReturnsSelf);
1026  return;
1027  }
1028  if (!OM->getReturnType()->isObjCIdType())
1029  return;
1030 
1031  ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl);
1032  if (!IDecl) {
1033  if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl))
1034  IDecl = CatDecl->getClassInterface();
1035  else if (ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(CDecl))
1036  IDecl = ImpDecl->getClassInterface();
1037  }
1038  if (!IDecl ||
1039  !IDecl->lookupInheritedClass(&Ctx.Idents.get(ClassName))) {
1040  migrateFactoryMethod(Ctx, CDecl, OM);
1041  return;
1042  }
1043  ReplaceWithInstancetype(Ctx, *this, OM);
1044 }
1045 
1047  if (!T->isAnyPointerType())
1048  return false;
1049  if (T->isObjCObjectPointerType() || T->isObjCBuiltinType() ||
1052  return false;
1053  // Also, typedef-of-pointer-to-incomplete-struct is something that we assume
1054  // is not an innter pointer type.
1055  QualType OrigT = T;
1056  while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr()))
1057  T = TD->getDecl()->getUnderlyingType();
1058  if (OrigT == T || !T->isPointerType())
1059  return true;
1060  const PointerType* PT = T->getAs<PointerType>();
1061  QualType UPointeeT = PT->getPointeeType().getUnqualifiedType();
1062  if (UPointeeT->isRecordType()) {
1063  const RecordType *RecordTy = UPointeeT->getAs<RecordType>();
1064  if (!RecordTy->getDecl()->isCompleteDefinition())
1065  return false;
1066  }
1067  return true;
1068 }
1069 
1070 /// Check whether the two versions match.
1071 static bool versionsMatch(const VersionTuple &X, const VersionTuple &Y) {
1072  return (X == Y);
1073 }
1074 
1075 /// AvailabilityAttrsMatch - This routine checks that if comparing two
1076 /// availability attributes, all their components match. It returns
1077 /// true, if not dealing with availability or when all components of
1078 /// availability attributes match. This routine is only called when
1079 /// the attributes are of the same kind.
1080 static bool AvailabilityAttrsMatch(Attr *At1, Attr *At2) {
1081  const AvailabilityAttr *AA1 = dyn_cast<AvailabilityAttr>(At1);
1082  if (!AA1)
1083  return true;
1084  const AvailabilityAttr *AA2 = dyn_cast<AvailabilityAttr>(At2);
1085 
1086  VersionTuple Introduced1 = AA1->getIntroduced();
1087  VersionTuple Deprecated1 = AA1->getDeprecated();
1088  VersionTuple Obsoleted1 = AA1->getObsoleted();
1089  bool IsUnavailable1 = AA1->getUnavailable();
1090  VersionTuple Introduced2 = AA2->getIntroduced();
1091  VersionTuple Deprecated2 = AA2->getDeprecated();
1092  VersionTuple Obsoleted2 = AA2->getObsoleted();
1093  bool IsUnavailable2 = AA2->getUnavailable();
1094  return (versionsMatch(Introduced1, Introduced2) &&
1095  versionsMatch(Deprecated1, Deprecated2) &&
1096  versionsMatch(Obsoleted1, Obsoleted2) &&
1097  IsUnavailable1 == IsUnavailable2);
1098 }
1099 
1100 static bool MatchTwoAttributeLists(const AttrVec &Attrs1, const AttrVec &Attrs2,
1101  bool &AvailabilityArgsMatch) {
1102  // This list is very small, so this need not be optimized.
1103  for (unsigned i = 0, e = Attrs1.size(); i != e; i++) {
1104  bool match = false;
1105  for (unsigned j = 0, f = Attrs2.size(); j != f; j++) {
1106  // Matching attribute kind only. Except for Availability attributes,
1107  // we are not getting into details of the attributes. For all practical purposes
1108  // this is sufficient.
1109  if (Attrs1[i]->getKind() == Attrs2[j]->getKind()) {
1110  if (AvailabilityArgsMatch)
1111  AvailabilityArgsMatch = AvailabilityAttrsMatch(Attrs1[i], Attrs2[j]);
1112  match = true;
1113  break;
1114  }
1115  }
1116  if (!match)
1117  return false;
1118  }
1119  return true;
1120 }
1121 
1122 /// AttributesMatch - This routine checks list of attributes for two
1123 /// decls. It returns false, if there is a mismatch in kind of
1124 /// attributes seen in the decls. It returns true if the two decls
1125 /// have list of same kind of attributes. Furthermore, when there
1126 /// are availability attributes in the two decls, it sets the
1127 /// AvailabilityArgsMatch to false if availability attributes have
1128 /// different versions, etc.
1129 static bool AttributesMatch(const Decl *Decl1, const Decl *Decl2,
1130  bool &AvailabilityArgsMatch) {
1131  if (!Decl1->hasAttrs() || !Decl2->hasAttrs()) {
1132  AvailabilityArgsMatch = (Decl1->hasAttrs() == Decl2->hasAttrs());
1133  return true;
1134  }
1135  AvailabilityArgsMatch = true;
1136  const AttrVec &Attrs1 = Decl1->getAttrs();
1137  const AttrVec &Attrs2 = Decl2->getAttrs();
1138  bool match = MatchTwoAttributeLists(Attrs1, Attrs2, AvailabilityArgsMatch);
1139  if (match && (Attrs2.size() > Attrs1.size()))
1140  return MatchTwoAttributeLists(Attrs2, Attrs1, AvailabilityArgsMatch);
1141  return match;
1142 }
1143 
1145  const char *Name) {
1146  if (!isIdentifierHead(Name[0]))
1147  return false;
1148  std::string NameString = Name;
1149  NameString[0] = toLowercase(NameString[0]);
1150  IdentifierInfo *II = &Ctx.Idents.get(NameString);
1151  return II->getTokenID() == tok::identifier;
1152 }
1153 
1154 bool ObjCMigrateASTConsumer::migrateProperty(ASTContext &Ctx,
1155  ObjCContainerDecl *D,
1156  ObjCMethodDecl *Method) {
1157  if (Method->isPropertyAccessor() || !Method->isInstanceMethod() ||
1158  Method->param_size() != 0)
1159  return false;
1160  // Is this method candidate to be a getter?
1161  QualType GRT = Method->getReturnType();
1162  if (GRT->isVoidType())
1163  return false;
1164 
1165  Selector GetterSelector = Method->getSelector();
1166  ObjCInstanceTypeFamily OIT_Family =
1167  Selector::getInstTypeMethodFamily(GetterSelector);
1168 
1169  if (OIT_Family != OIT_None)
1170  return false;
1171 
1172  IdentifierInfo *getterName = GetterSelector.getIdentifierInfoForSlot(0);
1173  Selector SetterSelector =
1175  PP.getSelectorTable(),
1176  getterName);
1177  ObjCMethodDecl *SetterMethod = D->getInstanceMethod(SetterSelector);
1178  unsigned LengthOfPrefix = 0;
1179  if (!SetterMethod) {
1180  // try a different naming convention for getter: isXxxxx
1181  StringRef getterNameString = getterName->getName();
1182  bool IsPrefix = getterNameString.startswith("is");
1183  // Note that we don't want to change an isXXX method of retainable object
1184  // type to property (readonly or otherwise).
1185  if (IsPrefix && GRT->isObjCRetainableType())
1186  return false;
1187  if (IsPrefix || getterNameString.startswith("get")) {
1188  LengthOfPrefix = (IsPrefix ? 2 : 3);
1189  const char *CGetterName = getterNameString.data() + LengthOfPrefix;
1190  // Make sure that first character after "is" or "get" prefix can
1191  // start an identifier.
1192  if (!IsValidIdentifier(Ctx, CGetterName))
1193  return false;
1194  if (CGetterName[0] && isUppercase(CGetterName[0])) {
1195  getterName = &Ctx.Idents.get(CGetterName);
1196  SetterSelector =
1198  PP.getSelectorTable(),
1199  getterName);
1200  SetterMethod = D->getInstanceMethod(SetterSelector);
1201  }
1202  }
1203  }
1204 
1205  if (SetterMethod) {
1206  if ((ASTMigrateActions & FrontendOptions::ObjCMT_ReadwriteProperty) == 0)
1207  return false;
1208  bool AvailabilityArgsMatch;
1209  if (SetterMethod->isDeprecated() ||
1210  !AttributesMatch(Method, SetterMethod, AvailabilityArgsMatch))
1211  return false;
1212 
1213  // Is this a valid setter, matching the target getter?
1214  QualType SRT = SetterMethod->getReturnType();
1215  if (!SRT->isVoidType())
1216  return false;
1217  const ParmVarDecl *argDecl = *SetterMethod->param_begin();
1218  QualType ArgType = argDecl->getType();
1219  if (!Ctx.hasSameUnqualifiedType(ArgType, GRT))
1220  return false;
1221  edit::Commit commit(*Editor);
1222  rewriteToObjCProperty(Method, SetterMethod, *NSAPIObj, commit,
1223  LengthOfPrefix,
1224  (ASTMigrateActions &
1226  (ASTMigrateActions &
1228  AvailabilityArgsMatch);
1229  Editor->commit(commit);
1230  return true;
1231  }
1232  else if (ASTMigrateActions & FrontendOptions::ObjCMT_ReadonlyProperty) {
1233  // Try a non-void method with no argument (and no setter or property of same name
1234  // as a 'readonly' property.
1235  edit::Commit commit(*Editor);
1236  rewriteToObjCProperty(Method, nullptr /*SetterMethod*/, *NSAPIObj, commit,
1237  LengthOfPrefix,
1238  (ASTMigrateActions &
1240  (ASTMigrateActions &
1242  /*AvailabilityArgsMatch*/false);
1243  Editor->commit(commit);
1244  return true;
1245  }
1246  return false;
1247 }
1248 
1249 void ObjCMigrateASTConsumer::migrateNsReturnsInnerPointer(ASTContext &Ctx,
1250  ObjCMethodDecl *OM) {
1251  if (OM->isImplicit() ||
1252  !OM->isInstanceMethod() ||
1253  OM->hasAttr<ObjCReturnsInnerPointerAttr>())
1254  return;
1255 
1256  QualType RT = OM->getReturnType();
1257  if (!TypeIsInnerPointer(RT) ||
1258  !NSAPIObj->isMacroDefined("NS_RETURNS_INNER_POINTER"))
1259  return;
1260 
1261  edit::Commit commit(*Editor);
1262  commit.insertBefore(OM->getEndLoc(), " NS_RETURNS_INNER_POINTER");
1263  Editor->commit(commit);
1264 }
1265 
1266 void ObjCMigrateASTConsumer::migratePropertyNsReturnsInnerPointer(ASTContext &Ctx,
1267  ObjCPropertyDecl *P) {
1268  QualType T = P->getType();
1269 
1270  if (!TypeIsInnerPointer(T) ||
1271  !NSAPIObj->isMacroDefined("NS_RETURNS_INNER_POINTER"))
1272  return;
1273  edit::Commit commit(*Editor);
1274  commit.insertBefore(P->getEndLoc(), " NS_RETURNS_INNER_POINTER ");
1275  Editor->commit(commit);
1276 }
1277 
1278 void ObjCMigrateASTConsumer::migrateAllMethodInstaceType(ASTContext &Ctx,
1279  ObjCContainerDecl *CDecl) {
1280  if (CDecl->isDeprecated() || IsCategoryNameWithDeprecatedSuffix(CDecl))
1281  return;
1282 
1283  // migrate methods which can have instancetype as their result type.
1284  for (auto *Method : CDecl->methods()) {
1285  if (Method->isDeprecated())
1286  continue;
1287  migrateMethodInstanceType(Ctx, CDecl, Method);
1288  }
1289 }
1290 
1291 void ObjCMigrateASTConsumer::migrateFactoryMethod(ASTContext &Ctx,
1292  ObjCContainerDecl *CDecl,
1293  ObjCMethodDecl *OM,
1294  ObjCInstanceTypeFamily OIT_Family) {
1295  if (OM->isInstanceMethod() ||
1296  OM->getReturnType() == Ctx.getObjCInstanceType() ||
1297  !OM->getReturnType()->isObjCIdType())
1298  return;
1299 
1300  // Candidate factory methods are + (id) NaMeXXX : ... which belong to a class
1301  // NSYYYNamE with matching names be at least 3 characters long.
1302  ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl);
1303  if (!IDecl) {
1304  if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl))
1305  IDecl = CatDecl->getClassInterface();
1306  else if (ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(CDecl))
1307  IDecl = ImpDecl->getClassInterface();
1308  }
1309  if (!IDecl)
1310  return;
1311 
1312  std::string StringClassName = IDecl->getName();
1313  StringRef LoweredClassName(StringClassName);
1314  std::string StringLoweredClassName = LoweredClassName.lower();
1315  LoweredClassName = StringLoweredClassName;
1316 
1317  IdentifierInfo *MethodIdName = OM->getSelector().getIdentifierInfoForSlot(0);
1318  // Handle method with no name at its first selector slot; e.g. + (id):(int)x.
1319  if (!MethodIdName)
1320  return;
1321 
1322  std::string MethodName = MethodIdName->getName();
1323  if (OIT_Family == OIT_Singleton || OIT_Family == OIT_ReturnsSelf) {
1324  StringRef STRefMethodName(MethodName);
1325  size_t len = 0;
1326  if (STRefMethodName.startswith("standard"))
1327  len = strlen("standard");
1328  else if (STRefMethodName.startswith("shared"))
1329  len = strlen("shared");
1330  else if (STRefMethodName.startswith("default"))
1331  len = strlen("default");
1332  else
1333  return;
1334  MethodName = STRefMethodName.substr(len);
1335  }
1336  std::string MethodNameSubStr = MethodName.substr(0, 3);
1337  StringRef MethodNamePrefix(MethodNameSubStr);
1338  std::string StringLoweredMethodNamePrefix = MethodNamePrefix.lower();
1339  MethodNamePrefix = StringLoweredMethodNamePrefix;
1340  size_t Ix = LoweredClassName.rfind(MethodNamePrefix);
1341  if (Ix == StringRef::npos)
1342  return;
1343  std::string ClassNamePostfix = LoweredClassName.substr(Ix);
1344  StringRef LoweredMethodName(MethodName);
1345  std::string StringLoweredMethodName = LoweredMethodName.lower();
1346  LoweredMethodName = StringLoweredMethodName;
1347  if (!LoweredMethodName.startswith(ClassNamePostfix))
1348  return;
1349  if (OIT_Family == OIT_ReturnsSelf)
1350  ReplaceWithClasstype(*this, OM);
1351  else
1352  ReplaceWithInstancetype(Ctx, *this, OM);
1353 }
1354 
1355 static bool IsVoidStarType(QualType Ty) {
1356  if (!Ty->isPointerType())
1357  return false;
1358 
1359  while (const TypedefType *TD = dyn_cast<TypedefType>(Ty.getTypePtr()))
1360  Ty = TD->getDecl()->getUnderlyingType();
1361 
1362  // Is the type void*?
1363  const PointerType* PT = Ty->getAs<PointerType>();
1365  return true;
1366  return IsVoidStarType(PT->getPointeeType());
1367 }
1368 
1369 /// AuditedType - This routine audits the type AT and returns false if it is one of known
1370 /// CF object types or of the "void *" variety. It returns true if we don't care about the type
1371 /// such as a non-pointer or pointers which have no ownership issues (such as "int *").
1372 static bool AuditedType (QualType AT) {
1373  if (!AT->isAnyPointerType() && !AT->isBlockPointerType())
1374  return true;
1375  // FIXME. There isn't much we can say about CF pointer type; or is there?
1377  IsVoidStarType(AT) ||
1378  // If an ObjC object is type, assuming that it is not a CF function and
1379  // that it is an un-audited function.
1381  return false;
1382  // All other pointers are assumed audited as harmless.
1383  return true;
1384 }
1385 
1386 void ObjCMigrateASTConsumer::AnnotateImplicitBridging(ASTContext &Ctx) {
1387  if (CFFunctionIBCandidates.empty())
1388  return;
1389  if (!NSAPIObj->isMacroDefined("CF_IMPLICIT_BRIDGING_ENABLED")) {
1390  CFFunctionIBCandidates.clear();
1391  FileId = FileID();
1392  return;
1393  }
1394  // Insert CF_IMPLICIT_BRIDGING_ENABLE/CF_IMPLICIT_BRIDGING_DISABLED
1395  const Decl *FirstFD = CFFunctionIBCandidates[0];
1396  const Decl *LastFD =
1397  CFFunctionIBCandidates[CFFunctionIBCandidates.size()-1];
1398  const char *PragmaString = "\nCF_IMPLICIT_BRIDGING_ENABLED\n\n";
1399  edit::Commit commit(*Editor);
1400  commit.insertBefore(FirstFD->getBeginLoc(), PragmaString);
1401  PragmaString = "\n\nCF_IMPLICIT_BRIDGING_DISABLED\n";
1402  SourceLocation EndLoc = LastFD->getEndLoc();
1403  // get location just past end of function location.
1404  EndLoc = PP.getLocForEndOfToken(EndLoc);
1405  if (isa<FunctionDecl>(LastFD)) {
1406  // For Methods, EndLoc points to the ending semcolon. So,
1407  // not of these extra work is needed.
1408  Token Tok;
1409  // get locaiton of token that comes after end of function.
1410  bool Failed = PP.getRawToken(EndLoc, Tok, /*IgnoreWhiteSpace=*/true);
1411  if (!Failed)
1412  EndLoc = Tok.getLocation();
1413  }
1414  commit.insertAfterToken(EndLoc, PragmaString);
1415  Editor->commit(commit);
1416  FileId = FileID();
1417  CFFunctionIBCandidates.clear();
1418 }
1419 
1420 void ObjCMigrateASTConsumer::migrateCFAnnotation(ASTContext &Ctx, const Decl *Decl) {
1421  if (Decl->isDeprecated())
1422  return;
1423 
1424  if (Decl->hasAttr<CFAuditedTransferAttr>()) {
1425  assert(CFFunctionIBCandidates.empty() &&
1426  "Cannot have audited functions/methods inside user "
1427  "provided CF_IMPLICIT_BRIDGING_ENABLE");
1428  return;
1429  }
1430 
1431  // Finction must be annotated first.
1432  if (const FunctionDecl *FuncDecl = dyn_cast<FunctionDecl>(Decl)) {
1433  CF_BRIDGING_KIND AuditKind = migrateAddFunctionAnnotation(Ctx, FuncDecl);
1434  if (AuditKind == CF_BRIDGING_ENABLE) {
1435  CFFunctionIBCandidates.push_back(Decl);
1436  if (FileId.isInvalid())
1437  FileId = PP.getSourceManager().getFileID(Decl->getLocation());
1438  }
1439  else if (AuditKind == CF_BRIDGING_MAY_INCLUDE) {
1440  if (!CFFunctionIBCandidates.empty()) {
1441  CFFunctionIBCandidates.push_back(Decl);
1442  if (FileId.isInvalid())
1443  FileId = PP.getSourceManager().getFileID(Decl->getLocation());
1444  }
1445  }
1446  else
1447  AnnotateImplicitBridging(Ctx);
1448  }
1449  else {
1450  migrateAddMethodAnnotation(Ctx, cast<ObjCMethodDecl>(Decl));
1451  AnnotateImplicitBridging(Ctx);
1452  }
1453 }
1454 
1455 void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
1456  const CallEffects &CE,
1457  const FunctionDecl *FuncDecl,
1458  bool ResultAnnotated) {
1459  // Annotate function.
1460  if (!ResultAnnotated) {
1461  RetEffect Ret = CE.getReturnValue();
1462  const char *AnnotationString = nullptr;
1463  if (Ret.getObjKind() == RetEffect::CF) {
1464  if (Ret.isOwned() && NSAPIObj->isMacroDefined("CF_RETURNS_RETAINED"))
1465  AnnotationString = " CF_RETURNS_RETAINED";
1466  else if (Ret.notOwned() &&
1467  NSAPIObj->isMacroDefined("CF_RETURNS_NOT_RETAINED"))
1468  AnnotationString = " CF_RETURNS_NOT_RETAINED";
1469  }
1470  else if (Ret.getObjKind() == RetEffect::ObjC) {
1471  if (Ret.isOwned() && NSAPIObj->isMacroDefined("NS_RETURNS_RETAINED"))
1472  AnnotationString = " NS_RETURNS_RETAINED";
1473  }
1474 
1475  if (AnnotationString) {
1476  edit::Commit commit(*Editor);
1477  commit.insertAfterToken(FuncDecl->getEndLoc(), AnnotationString);
1478  Editor->commit(commit);
1479  }
1480  }
1481  ArrayRef<ArgEffect> AEArgs = CE.getArgs();
1482  unsigned i = 0;
1483  for (FunctionDecl::param_const_iterator pi = FuncDecl->param_begin(),
1484  pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) {
1485  const ParmVarDecl *pd = *pi;
1486  ArgEffect AE = AEArgs[i];
1487  if (AE == DecRef && !pd->hasAttr<CFConsumedAttr>() &&
1488  NSAPIObj->isMacroDefined("CF_CONSUMED")) {
1489  edit::Commit commit(*Editor);
1490  commit.insertBefore(pd->getLocation(), "CF_CONSUMED ");
1491  Editor->commit(commit);
1492  }
1493  else if (AE == DecRefMsg && !pd->hasAttr<NSConsumedAttr>() &&
1494  NSAPIObj->isMacroDefined("NS_CONSUMED")) {
1495  edit::Commit commit(*Editor);
1496  commit.insertBefore(pd->getLocation(), "NS_CONSUMED ");
1497  Editor->commit(commit);
1498  }
1499  }
1500 }
1501 
1502 ObjCMigrateASTConsumer::CF_BRIDGING_KIND
1503  ObjCMigrateASTConsumer::migrateAddFunctionAnnotation(
1504  ASTContext &Ctx,
1505  const FunctionDecl *FuncDecl) {
1506  if (FuncDecl->hasBody())
1507  return CF_BRIDGING_NONE;
1508 
1509  CallEffects CE = CallEffects::getEffect(FuncDecl);
1510  bool FuncIsReturnAnnotated = (FuncDecl->hasAttr<CFReturnsRetainedAttr>() ||
1511  FuncDecl->hasAttr<CFReturnsNotRetainedAttr>() ||
1512  FuncDecl->hasAttr<NSReturnsRetainedAttr>() ||
1513  FuncDecl->hasAttr<NSReturnsNotRetainedAttr>() ||
1514  FuncDecl->hasAttr<NSReturnsAutoreleasedAttr>());
1515 
1516  // Trivial case of when function is annotated and has no argument.
1517  if (FuncIsReturnAnnotated && FuncDecl->getNumParams() == 0)
1518  return CF_BRIDGING_NONE;
1519 
1520  bool ReturnCFAudited = false;
1521  if (!FuncIsReturnAnnotated) {
1522  RetEffect Ret = CE.getReturnValue();
1523  if (Ret.getObjKind() == RetEffect::CF &&
1524  (Ret.isOwned() || Ret.notOwned()))
1525  ReturnCFAudited = true;
1526  else if (!AuditedType(FuncDecl->getReturnType()))
1527  return CF_BRIDGING_NONE;
1528  }
1529 
1530  // At this point result type is audited for potential inclusion.
1531  // Now, how about argument types.
1532  ArrayRef<ArgEffect> AEArgs = CE.getArgs();
1533  unsigned i = 0;
1534  bool ArgCFAudited = false;
1535  for (FunctionDecl::param_const_iterator pi = FuncDecl->param_begin(),
1536  pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) {
1537  const ParmVarDecl *pd = *pi;
1538  ArgEffect AE = AEArgs[i];
1539  if (AE == DecRef /*CFConsumed annotated*/ || AE == IncRef) {
1540  if (AE == DecRef && !pd->hasAttr<CFConsumedAttr>())
1541  ArgCFAudited = true;
1542  else if (AE == IncRef)
1543  ArgCFAudited = true;
1544  }
1545  else {
1546  QualType AT = pd->getType();
1547  if (!AuditedType(AT)) {
1548  AddCFAnnotations(Ctx, CE, FuncDecl, FuncIsReturnAnnotated);
1549  return CF_BRIDGING_NONE;
1550  }
1551  }
1552  }
1553  if (ReturnCFAudited || ArgCFAudited)
1554  return CF_BRIDGING_ENABLE;
1555 
1556  return CF_BRIDGING_MAY_INCLUDE;
1557 }
1558 
1559 void ObjCMigrateASTConsumer::migrateARCSafeAnnotation(ASTContext &Ctx,
1560  ObjCContainerDecl *CDecl) {
1561  if (!isa<ObjCInterfaceDecl>(CDecl) || CDecl->isDeprecated())
1562  return;
1563 
1564  // migrate methods which can have instancetype as their result type.
1565  for (const auto *Method : CDecl->methods())
1566  migrateCFAnnotation(Ctx, Method);
1567 }
1568 
1569 void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
1570  const CallEffects &CE,
1571  const ObjCMethodDecl *MethodDecl,
1572  bool ResultAnnotated) {
1573  // Annotate function.
1574  if (!ResultAnnotated) {
1575  RetEffect Ret = CE.getReturnValue();
1576  const char *AnnotationString = nullptr;
1577  if (Ret.getObjKind() == RetEffect::CF) {
1578  if (Ret.isOwned() && NSAPIObj->isMacroDefined("CF_RETURNS_RETAINED"))
1579  AnnotationString = " CF_RETURNS_RETAINED";
1580  else if (Ret.notOwned() &&
1581  NSAPIObj->isMacroDefined("CF_RETURNS_NOT_RETAINED"))
1582  AnnotationString = " CF_RETURNS_NOT_RETAINED";
1583  }
1584  else if (Ret.getObjKind() == RetEffect::ObjC) {
1585  ObjCMethodFamily OMF = MethodDecl->getMethodFamily();
1586  switch (OMF) {
1587  case clang::OMF_alloc:
1588  case clang::OMF_new:
1589  case clang::OMF_copy:
1590  case clang::OMF_init:
1592  break;
1593 
1594  default:
1595  if (Ret.isOwned() && NSAPIObj->isMacroDefined("NS_RETURNS_RETAINED"))
1596  AnnotationString = " NS_RETURNS_RETAINED";
1597  break;
1598  }
1599  }
1600 
1601  if (AnnotationString) {
1602  edit::Commit commit(*Editor);
1603  commit.insertBefore(MethodDecl->getEndLoc(), AnnotationString);
1604  Editor->commit(commit);
1605  }
1606  }
1607  ArrayRef<ArgEffect> AEArgs = CE.getArgs();
1608  unsigned i = 0;
1609  for (ObjCMethodDecl::param_const_iterator pi = MethodDecl->param_begin(),
1610  pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) {
1611  const ParmVarDecl *pd = *pi;
1612  ArgEffect AE = AEArgs[i];
1613  if (AE == DecRef && !pd->hasAttr<CFConsumedAttr>() &&
1614  NSAPIObj->isMacroDefined("CF_CONSUMED")) {
1615  edit::Commit commit(*Editor);
1616  commit.insertBefore(pd->getLocation(), "CF_CONSUMED ");
1617  Editor->commit(commit);
1618  }
1619  }
1620 }
1621 
1622 void ObjCMigrateASTConsumer::migrateAddMethodAnnotation(
1623  ASTContext &Ctx,
1624  const ObjCMethodDecl *MethodDecl) {
1625  if (MethodDecl->hasBody() || MethodDecl->isImplicit())
1626  return;
1627 
1628  CallEffects CE = CallEffects::getEffect(MethodDecl);
1629  bool MethodIsReturnAnnotated = (MethodDecl->hasAttr<CFReturnsRetainedAttr>() ||
1630  MethodDecl->hasAttr<CFReturnsNotRetainedAttr>() ||
1631  MethodDecl->hasAttr<NSReturnsRetainedAttr>() ||
1632  MethodDecl->hasAttr<NSReturnsNotRetainedAttr>() ||
1633  MethodDecl->hasAttr<NSReturnsAutoreleasedAttr>());
1634 
1635  if (CE.getReceiver() == DecRefMsg &&
1636  !MethodDecl->hasAttr<NSConsumesSelfAttr>() &&
1637  MethodDecl->getMethodFamily() != OMF_init &&
1638  MethodDecl->getMethodFamily() != OMF_release &&
1639  NSAPIObj->isMacroDefined("NS_CONSUMES_SELF")) {
1640  edit::Commit commit(*Editor);
1641  commit.insertBefore(MethodDecl->getEndLoc(), " NS_CONSUMES_SELF");
1642  Editor->commit(commit);
1643  }
1644 
1645  // Trivial case of when function is annotated and has no argument.
1646  if (MethodIsReturnAnnotated &&
1647  (MethodDecl->param_begin() == MethodDecl->param_end()))
1648  return;
1649 
1650  if (!MethodIsReturnAnnotated) {
1651  RetEffect Ret = CE.getReturnValue();
1652  if ((Ret.getObjKind() == RetEffect::CF ||
1653  Ret.getObjKind() == RetEffect::ObjC) &&
1654  (Ret.isOwned() || Ret.notOwned())) {
1655  AddCFAnnotations(Ctx, CE, MethodDecl, false);
1656  return;
1657  } else if (!AuditedType(MethodDecl->getReturnType()))
1658  return;
1659  }
1660 
1661  // At this point result type is either annotated or audited.
1662  // Now, how about argument types.
1663  ArrayRef<ArgEffect> AEArgs = CE.getArgs();
1664  unsigned i = 0;
1665  for (ObjCMethodDecl::param_const_iterator pi = MethodDecl->param_begin(),
1666  pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) {
1667  const ParmVarDecl *pd = *pi;
1668  ArgEffect AE = AEArgs[i];
1669  if ((AE == DecRef && !pd->hasAttr<CFConsumedAttr>()) || AE == IncRef ||
1670  !AuditedType(pd->getType())) {
1671  AddCFAnnotations(Ctx, CE, MethodDecl, MethodIsReturnAnnotated);
1672  return;
1673  }
1674  }
1675 }
1676 
1677 namespace {
1678 class SuperInitChecker : public RecursiveASTVisitor<SuperInitChecker> {
1679 public:
1680  bool shouldVisitTemplateInstantiations() const { return false; }
1681  bool shouldWalkTypesOfTypeLocs() const { return false; }
1682 
1683  bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
1685  if (E->getMethodFamily() == OMF_init)
1686  return false;
1687  }
1688  return true;
1689  }
1690 };
1691 } // end anonymous namespace
1692 
1693 static bool hasSuperInitCall(const ObjCMethodDecl *MD) {
1694  return !SuperInitChecker().TraverseStmt(MD->getBody());
1695 }
1696 
1697 void ObjCMigrateASTConsumer::inferDesignatedInitializers(
1698  ASTContext &Ctx,
1699  const ObjCImplementationDecl *ImplD) {
1700 
1701  const ObjCInterfaceDecl *IFace = ImplD->getClassInterface();
1702  if (!IFace || IFace->hasDesignatedInitializers())
1703  return;
1704  if (!NSAPIObj->isMacroDefined("NS_DESIGNATED_INITIALIZER"))
1705  return;
1706 
1707  for (const auto *MD : ImplD->instance_methods()) {
1708  if (MD->isDeprecated() ||
1709  MD->getMethodFamily() != OMF_init ||
1710  MD->isDesignatedInitializerForTheInterface())
1711  continue;
1712  const ObjCMethodDecl *IFaceM = IFace->getMethod(MD->getSelector(),
1713  /*isInstance=*/true);
1714  if (!IFaceM)
1715  continue;
1716  if (hasSuperInitCall(MD)) {
1717  edit::Commit commit(*Editor);
1718  commit.insert(IFaceM->getEndLoc(), " NS_DESIGNATED_INITIALIZER");
1719  Editor->commit(commit);
1720  }
1721  }
1722 }
1723 
1724 bool ObjCMigrateASTConsumer::InsertFoundation(ASTContext &Ctx,
1725  SourceLocation Loc) {
1726  if (FoundationIncluded)
1727  return true;
1728  if (Loc.isInvalid())
1729  return false;
1730  auto *nsEnumId = &Ctx.Idents.get("NS_ENUM");
1731  if (PP.getMacroDefinitionAtLoc(nsEnumId, Loc)) {
1732  FoundationIncluded = true;
1733  return true;
1734  }
1735  edit::Commit commit(*Editor);
1736  if (Ctx.getLangOpts().Modules)
1737  commit.insert(Loc, "#ifndef NS_ENUM\n@import Foundation;\n#endif\n");
1738  else
1739  commit.insert(Loc, "#ifndef NS_ENUM\n#import <Foundation/Foundation.h>\n#endif\n");
1740  Editor->commit(commit);
1741  FoundationIncluded = true;
1742  return true;
1743 }
1744 
1745 namespace {
1746 
1747 class RewritesReceiver : public edit::EditsReceiver {
1748  Rewriter &Rewrite;
1749 
1750 public:
1751  RewritesReceiver(Rewriter &Rewrite) : Rewrite(Rewrite) { }
1752 
1753  void insert(SourceLocation loc, StringRef text) override {
1754  Rewrite.InsertText(loc, text);
1755  }
1756  void replace(CharSourceRange range, StringRef text) override {
1757  Rewrite.ReplaceText(range.getBegin(), Rewrite.getRangeSize(range), text);
1758  }
1759 };
1760 
1761 class JSONEditWriter : public edit::EditsReceiver {
1762  SourceManager &SourceMgr;
1763  llvm::raw_ostream &OS;
1764 
1765 public:
1766  JSONEditWriter(SourceManager &SM, llvm::raw_ostream &OS)
1767  : SourceMgr(SM), OS(OS) {
1768  OS << "[\n";
1769  }
1770  ~JSONEditWriter() override { OS << "]\n"; }
1771 
1772 private:
1773  struct EntryWriter {
1774  SourceManager &SourceMgr;
1775  llvm::raw_ostream &OS;
1776 
1777  EntryWriter(SourceManager &SM, llvm::raw_ostream &OS)
1778  : SourceMgr(SM), OS(OS) {
1779  OS << " {\n";
1780  }
1781  ~EntryWriter() {
1782  OS << " },\n";
1783  }
1784 
1785  void writeLoc(SourceLocation Loc) {
1786  FileID FID;
1787  unsigned Offset;
1788  std::tie(FID, Offset) = SourceMgr.getDecomposedLoc(Loc);
1789  assert(FID.isValid());
1790  SmallString<200> Path =
1791  StringRef(SourceMgr.getFileEntryForID(FID)->getName());
1792  llvm::sys::fs::make_absolute(Path);
1793  OS << " \"file\": \"";
1794  OS.write_escaped(Path.str()) << "\",\n";
1795  OS << " \"offset\": " << Offset << ",\n";
1796  }
1797 
1798  void writeRemove(CharSourceRange Range) {
1799  assert(Range.isCharRange());
1800  std::pair<FileID, unsigned> Begin =
1801  SourceMgr.getDecomposedLoc(Range.getBegin());
1802  std::pair<FileID, unsigned> End =
1803  SourceMgr.getDecomposedLoc(Range.getEnd());
1804  assert(Begin.first == End.first);
1805  assert(Begin.second <= End.second);
1806  unsigned Length = End.second - Begin.second;
1807 
1808  OS << " \"remove\": " << Length << ",\n";
1809  }
1810 
1811  void writeText(StringRef Text) {
1812  OS << " \"text\": \"";
1813  OS.write_escaped(Text) << "\",\n";
1814  }
1815  };
1816 
1817  void insert(SourceLocation Loc, StringRef Text) override {
1818  EntryWriter Writer(SourceMgr, OS);
1819  Writer.writeLoc(Loc);
1820  Writer.writeText(Text);
1821  }
1822 
1823  void replace(CharSourceRange Range, StringRef Text) override {
1824  EntryWriter Writer(SourceMgr, OS);
1825  Writer.writeLoc(Range.getBegin());
1826  Writer.writeRemove(Range);
1827  Writer.writeText(Text);
1828  }
1829 
1830  void remove(CharSourceRange Range) override {
1831  EntryWriter Writer(SourceMgr, OS);
1832  Writer.writeLoc(Range.getBegin());
1833  Writer.writeRemove(Range);
1834  }
1835 };
1836 
1837 } // end anonymous namespace
1838 
1839 void ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) {
1840 
1842  if (ASTMigrateActions & FrontendOptions::ObjCMT_MigrateDecls) {
1843  for (DeclContext::decl_iterator D = TU->decls_begin(), DEnd = TU->decls_end();
1844  D != DEnd; ++D) {
1845  FileID FID = PP.getSourceManager().getFileID((*D)->getLocation());
1846  if (FID.isValid())
1847  if (FileId.isValid() && FileId != FID) {
1848  if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation)
1849  AnnotateImplicitBridging(Ctx);
1850  }
1851 
1852  if (ObjCInterfaceDecl *CDecl = dyn_cast<ObjCInterfaceDecl>(*D))
1853  if (canModify(CDecl))
1854  migrateObjCContainerDecl(Ctx, CDecl);
1855  if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(*D)) {
1856  if (canModify(CatDecl))
1857  migrateObjCContainerDecl(Ctx, CatDecl);
1858  }
1859  else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(*D)) {
1860  ObjCProtocolDecls.insert(PDecl->getCanonicalDecl());
1861  if (canModify(PDecl))
1862  migrateObjCContainerDecl(Ctx, PDecl);
1863  }
1864  else if (const ObjCImplementationDecl *ImpDecl =
1865  dyn_cast<ObjCImplementationDecl>(*D)) {
1866  if ((ASTMigrateActions & FrontendOptions::ObjCMT_ProtocolConformance) &&
1867  canModify(ImpDecl))
1868  migrateProtocolConformance(Ctx, ImpDecl);
1869  }
1870  else if (const EnumDecl *ED = dyn_cast<EnumDecl>(*D)) {
1871  if (!(ASTMigrateActions & FrontendOptions::ObjCMT_NsMacros))
1872  continue;
1873  if (!canModify(ED))
1874  continue;
1876  if (++N != DEnd) {
1877  const TypedefDecl *TD = dyn_cast<TypedefDecl>(*N);
1878  if (migrateNSEnumDecl(Ctx, ED, TD) && TD)
1879  D++;
1880  }
1881  else
1882  migrateNSEnumDecl(Ctx, ED, /*TypedefDecl */nullptr);
1883  }
1884  else if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(*D)) {
1885  if (!(ASTMigrateActions & FrontendOptions::ObjCMT_NsMacros))
1886  continue;
1887  if (!canModify(TD))
1888  continue;
1890  if (++N == DEnd)
1891  continue;
1892  if (const EnumDecl *ED = dyn_cast<EnumDecl>(*N)) {
1893  if (canModify(ED)) {
1894  if (++N != DEnd)
1895  if (const TypedefDecl *TDF = dyn_cast<TypedefDecl>(*N)) {
1896  // prefer typedef-follows-enum to enum-follows-typedef pattern.
1897  if (migrateNSEnumDecl(Ctx, ED, TDF)) {
1898  ++D; ++D;
1899  CacheObjCNSIntegerTypedefed(TD);
1900  continue;
1901  }
1902  }
1903  if (migrateNSEnumDecl(Ctx, ED, TD)) {
1904  ++D;
1905  continue;
1906  }
1907  }
1908  }
1909  CacheObjCNSIntegerTypedefed(TD);
1910  }
1911  else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*D)) {
1912  if ((ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) &&
1913  canModify(FD))
1914  migrateCFAnnotation(Ctx, FD);
1915  }
1916 
1917  if (ObjCContainerDecl *CDecl = dyn_cast<ObjCContainerDecl>(*D)) {
1918  bool CanModify = canModify(CDecl);
1919  // migrate methods which can have instancetype as their result type.
1920  if ((ASTMigrateActions & FrontendOptions::ObjCMT_Instancetype) &&
1921  CanModify)
1922  migrateAllMethodInstaceType(Ctx, CDecl);
1923  // annotate methods with CF annotations.
1924  if ((ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) &&
1925  CanModify)
1926  migrateARCSafeAnnotation(Ctx, CDecl);
1927  }
1928 
1929  if (const ObjCImplementationDecl *
1930  ImplD = dyn_cast<ObjCImplementationDecl>(*D)) {
1931  if ((ASTMigrateActions & FrontendOptions::ObjCMT_DesignatedInitializer) &&
1932  canModify(ImplD))
1933  inferDesignatedInitializers(Ctx, ImplD);
1934  }
1935  }
1936  if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation)
1937  AnnotateImplicitBridging(Ctx);
1938  }
1939 
1940  if (IsOutputFile) {
1941  std::error_code EC;
1942  llvm::raw_fd_ostream OS(MigrateDir, EC, llvm::sys::fs::F_None);
1943  if (EC) {
1944  DiagnosticsEngine &Diags = Ctx.getDiagnostics();
1945  Diags.Report(Diags.getCustomDiagID(DiagnosticsEngine::Error, "%0"))
1946  << EC.message();
1947  return;
1948  }
1949 
1950  JSONEditWriter Writer(Ctx.getSourceManager(), OS);
1951  Editor->applyRewrites(Writer);
1952  return;
1953  }
1954 
1955  Rewriter rewriter(Ctx.getSourceManager(), Ctx.getLangOpts());
1956  RewritesReceiver Rec(rewriter);
1957  Editor->applyRewrites(Rec);
1958 
1960  I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) {
1961  FileID FID = I->first;
1962  RewriteBuffer &buf = I->second;
1963  const FileEntry *file = Ctx.getSourceManager().getFileEntryForID(FID);
1964  assert(file);
1965  SmallString<512> newText;
1966  llvm::raw_svector_ostream vecOS(newText);
1967  buf.write(vecOS);
1968  std::unique_ptr<llvm::MemoryBuffer> memBuf(
1969  llvm::MemoryBuffer::getMemBufferCopy(
1970  StringRef(newText.data(), newText.size()), file->getName()));
1971  SmallString<64> filePath(file->getName());
1972  FileMgr.FixupRelativePath(filePath);
1973  Remapper.remap(filePath.str(), std::move(memBuf));
1974  }
1975 
1976  if (IsOutputFile) {
1977  Remapper.flushToFile(MigrateDir, Ctx.getDiagnostics());
1978  } else {
1979  Remapper.flushToDisk(MigrateDir, Ctx.getDiagnostics());
1980  }
1981 }
1982 
1985  return true;
1986 }
1987 
1988 static std::vector<std::string> getWhiteListFilenames(StringRef DirPath) {
1989  using namespace llvm::sys::fs;
1990  using namespace llvm::sys::path;
1991 
1992  std::vector<std::string> Filenames;
1993  if (DirPath.empty() || !is_directory(DirPath))
1994  return Filenames;
1995 
1996  std::error_code EC;
1997  directory_iterator DI = directory_iterator(DirPath, EC);
1998  directory_iterator DE;
1999  for (; !EC && DI != DE; DI = DI.increment(EC)) {
2000  if (is_regular_file(DI->path()))
2001  Filenames.push_back(filename(DI->path()));
2002  }
2003 
2004  return Filenames;
2005 }
2006 
2007 std::unique_ptr<ASTConsumer>
2011  unsigned ObjCMTAction = CI.getFrontendOpts().ObjCMTAction;
2012  unsigned ObjCMTOpts = ObjCMTAction;
2013  // These are companion flags, they do not enable transformations.
2014  ObjCMTOpts &= ~(FrontendOptions::ObjCMT_AtomicProperty |
2016  if (ObjCMTOpts == FrontendOptions::ObjCMT_None) {
2017  // If no specific option was given, enable literals+subscripting transforms
2018  // by default.
2019  ObjCMTAction |= FrontendOptions::ObjCMT_Literals |
2021  }
2022  CI.getPreprocessor().addPPCallbacks(std::unique_ptr<PPCallbacks>(PPRec));
2023  std::vector<std::string> WhiteList =
2025  return llvm::make_unique<ObjCMigrateASTConsumer>(
2026  CI.getFrontendOpts().OutputFile, ObjCMTAction, Remapper,
2027  CI.getFileManager(), PPRec, CI.getPreprocessor(),
2028  /*isOutputFile=*/true, WhiteList);
2029 }
2030 
2031 namespace {
2032 struct EditEntry {
2033  const FileEntry *File;
2034  unsigned Offset;
2035  unsigned RemoveLen;
2036  std::string Text;
2037 
2038  EditEntry() : File(), Offset(), RemoveLen() {}
2039 };
2040 } // end anonymous namespace
2041 
2042 namespace llvm {
2043 template<> struct DenseMapInfo<EditEntry> {
2044  static inline EditEntry getEmptyKey() {
2045  EditEntry Entry;
2046  Entry.Offset = unsigned(-1);
2047  return Entry;
2048  }
2049  static inline EditEntry getTombstoneKey() {
2050  EditEntry Entry;
2051  Entry.Offset = unsigned(-2);
2052  return Entry;
2053  }
2054  static unsigned getHashValue(const EditEntry& Val) {
2055  llvm::FoldingSetNodeID ID;
2056  ID.AddPointer(Val.File);
2057  ID.AddInteger(Val.Offset);
2058  ID.AddInteger(Val.RemoveLen);
2059  ID.AddString(Val.Text);
2060  return ID.ComputeHash();
2061  }
2062  static bool isEqual(const EditEntry &LHS, const EditEntry &RHS) {
2063  return LHS.File == RHS.File &&
2064  LHS.Offset == RHS.Offset &&
2065  LHS.RemoveLen == RHS.RemoveLen &&
2066  LHS.Text == RHS.Text;
2067  }
2068 };
2069 } // end namespace llvm
2070 
2071 namespace {
2072 class RemapFileParser {
2073  FileManager &FileMgr;
2074 
2075 public:
2076  RemapFileParser(FileManager &FileMgr) : FileMgr(FileMgr) { }
2077 
2078  bool parse(StringRef File, SmallVectorImpl<EditEntry> &Entries) {
2079  using namespace llvm::yaml;
2080 
2081  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
2082  llvm::MemoryBuffer::getFile(File);
2083  if (!FileBufOrErr)
2084  return true;
2085 
2086  llvm::SourceMgr SM;
2087  Stream YAMLStream(FileBufOrErr.get()->getMemBufferRef(), SM);
2088  document_iterator I = YAMLStream.begin();
2089  if (I == YAMLStream.end())
2090  return true;
2091  Node *Root = I->getRoot();
2092  if (!Root)
2093  return true;
2094 
2095  SequenceNode *SeqNode = dyn_cast<SequenceNode>(Root);
2096  if (!SeqNode)
2097  return true;
2098 
2099  for (SequenceNode::iterator
2100  AI = SeqNode->begin(), AE = SeqNode->end(); AI != AE; ++AI) {
2101  MappingNode *MapNode = dyn_cast<MappingNode>(&*AI);
2102  if (!MapNode)
2103  continue;
2104  parseEdit(MapNode, Entries);
2105  }
2106 
2107  return false;
2108  }
2109 
2110 private:
2111  void parseEdit(llvm::yaml::MappingNode *Node,
2112  SmallVectorImpl<EditEntry> &Entries) {
2113  using namespace llvm::yaml;
2114  EditEntry Entry;
2115  bool Ignore = false;
2116 
2117  for (MappingNode::iterator
2118  KVI = Node->begin(), KVE = Node->end(); KVI != KVE; ++KVI) {
2119  ScalarNode *KeyString = dyn_cast<ScalarNode>((*KVI).getKey());
2120  if (!KeyString)
2121  continue;
2122  SmallString<10> KeyStorage;
2123  StringRef Key = KeyString->getValue(KeyStorage);
2124 
2125  ScalarNode *ValueString = dyn_cast<ScalarNode>((*KVI).getValue());
2126  if (!ValueString)
2127  continue;
2128  SmallString<64> ValueStorage;
2129  StringRef Val = ValueString->getValue(ValueStorage);
2130 
2131  if (Key == "file") {
2132  const FileEntry *FE = FileMgr.getFile(Val);
2133  if (!FE)
2134  Ignore = true;
2135  Entry.File = FE;
2136  } else if (Key == "offset") {
2137  if (Val.getAsInteger(10, Entry.Offset))
2138  Ignore = true;
2139  } else if (Key == "remove") {
2140  if (Val.getAsInteger(10, Entry.RemoveLen))
2141  Ignore = true;
2142  } else if (Key == "text") {
2143  Entry.Text = Val;
2144  }
2145  }
2146 
2147  if (!Ignore)
2148  Entries.push_back(Entry);
2149  }
2150 };
2151 } // end anonymous namespace
2152 
2153 static bool reportDiag(const Twine &Err, DiagnosticsEngine &Diag) {
2155  << Err.str();
2156  return true;
2157 }
2158 
2159 static std::string applyEditsToTemp(const FileEntry *FE,
2160  ArrayRef<EditEntry> Edits,
2161  FileManager &FileMgr,
2163  using namespace llvm::sys;
2164 
2165  SourceManager SM(Diag, FileMgr);
2167  LangOptions LangOpts;
2168  edit::EditedSource Editor(SM, LangOpts);
2170  I = Edits.begin(), E = Edits.end(); I != E; ++I) {
2171  const EditEntry &Entry = *I;
2172  assert(Entry.File == FE);
2173  SourceLocation Loc =
2174  SM.getLocForStartOfFile(FID).getLocWithOffset(Entry.Offset);
2176  if (Entry.RemoveLen != 0) {
2177  Range = CharSourceRange::getCharRange(Loc,
2178  Loc.getLocWithOffset(Entry.RemoveLen));
2179  }
2180 
2181  edit::Commit commit(Editor);
2182  if (Range.isInvalid()) {
2183  commit.insert(Loc, Entry.Text);
2184  } else if (Entry.Text.empty()) {
2185  commit.remove(Range);
2186  } else {
2187  commit.replace(Range, Entry.Text);
2188  }
2189  Editor.commit(commit);
2190  }
2191 
2192  Rewriter rewriter(SM, LangOpts);
2193  RewritesReceiver Rec(rewriter);
2194  Editor.applyRewrites(Rec, /*adjustRemovals=*/false);
2195 
2196  const RewriteBuffer *Buf = rewriter.getRewriteBufferFor(FID);
2197  SmallString<512> NewText;
2198  llvm::raw_svector_ostream OS(NewText);
2199  Buf->write(OS);
2200 
2201  SmallString<64> TempPath;
2202  int FD;
2203  if (fs::createTemporaryFile(path::filename(FE->getName()),
2204  path::extension(FE->getName()).drop_front(), FD,
2205  TempPath)) {
2206  reportDiag("Could not create file: " + TempPath.str(), Diag);
2207  return std::string();
2208  }
2209 
2210  llvm::raw_fd_ostream TmpOut(FD, /*shouldClose=*/true);
2211  TmpOut.write(NewText.data(), NewText.size());
2212  TmpOut.close();
2213 
2214  return TempPath.str();
2215 }
2216 
2218  std::vector<std::pair<std::string,std::string> > &remap,
2219  ArrayRef<StringRef> remapFiles,
2220  DiagnosticConsumer *DiagClient) {
2221  bool hasErrorOccurred = false;
2222 
2223  FileSystemOptions FSOpts;
2224  FileManager FileMgr(FSOpts);
2225  RemapFileParser Parser(FileMgr);
2226 
2229  new DiagnosticsEngine(DiagID, new DiagnosticOptions,
2230  DiagClient, /*ShouldOwnClient=*/false));
2231 
2232  typedef llvm::DenseMap<const FileEntry *, std::vector<EditEntry> >
2233  FileEditEntriesTy;
2234  FileEditEntriesTy FileEditEntries;
2235 
2236  llvm::DenseSet<EditEntry> EntriesSet;
2237 
2239  I = remapFiles.begin(), E = remapFiles.end(); I != E; ++I) {
2241  if (Parser.parse(*I, Entries))
2242  continue;
2243 
2245  EI = Entries.begin(), EE = Entries.end(); EI != EE; ++EI) {
2246  EditEntry &Entry = *EI;
2247  if (!Entry.File)
2248  continue;
2249  std::pair<llvm::DenseSet<EditEntry>::iterator, bool>
2250  Insert = EntriesSet.insert(Entry);
2251  if (!Insert.second)
2252  continue;
2253 
2254  FileEditEntries[Entry.File].push_back(Entry);
2255  }
2256  }
2257 
2258  for (FileEditEntriesTy::iterator
2259  I = FileEditEntries.begin(), E = FileEditEntries.end(); I != E; ++I) {
2260  std::string TempFile = applyEditsToTemp(I->first, I->second,
2261  FileMgr, *Diags);
2262  if (TempFile.empty()) {
2263  hasErrorOccurred = true;
2264  continue;
2265  }
2266 
2267  remap.emplace_back(I->first->getName(), TempFile);
2268  }
2269 
2270  return hasErrorOccurred;
2271 }
std::string OutputFile
The output file, if any.
SourceLocation getLocForStartOfFile(FileID FID) const
Return the source location corresponding to the first byte of the specified file. ...
The receiver is the instance of the superclass object.
Definition: ExprObjC.h:1061
bool BeginInvocation(CompilerInstance &CI) override
Callback before starting processing a single input, giving the opportunity to modify the CompilerInvo...
Definition: ObjCMT.cpp:1983
Defines the clang::ASTContext interface.
bool remove(CharSourceRange range)
Definition: Commit.cpp:92
Encapsulates the retain count semantics on the arguments, return value, and receiver (if any) of a fu...
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override
Create the AST consumer object for this action, if supported.
Definition: ObjCMT.cpp:194
static bool AttributesMatch(const Decl *Decl1, const Decl *Decl2, bool &AvailabilityArgsMatch)
AttributesMatch - This routine checks list of attributes for two decls.
Definition: ObjCMT.cpp:1129
Represents a function declaration or definition.
Definition: Decl.h:1732
static bool MatchTwoAttributeLists(const AttrVec &Attrs1, const AttrVec &Attrs2, bool &AvailabilityArgsMatch)
Definition: ObjCMT.cpp:1100
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
The receiver is an object instance.
Definition: ExprObjC.h:1055
SourceLocation getLocWithOffset(int Offset) const
Return a source location with the specified offset from this SourceLocation.
std::string ObjCMTWhiteListPath
Smart pointer class that efficiently represents Objective-C method names.
SelectorTable & getSelectorTable()
Definition: Preprocessor.h:837
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition: Type.h:2543
QualType getPointeeType() const
Definition: Type.h:2556
A (possibly-)qualified type.
Definition: Type.h:642
bool isBlockPointerType() const
Definition: Type.h:6290
unsigned param_size() const
Definition: DeclObjC.h:341
bool rewriteToObjCSubscriptSyntax(const ObjCMessageExpr *Msg, const NSAPI &NS, Commit &commit)
Implements support for file system lookup, file system caching, and directory search management...
Definition: FileManager.h:117
ObjCInterfaceDecl * getClassInterface()
Definition: DeclObjC.cpp:1144
ASTConsumer - This is an abstract interface that should be implemented by clients that read ASTs...
Definition: ASTConsumer.h:34
Defines the clang::FileManager interface and associated types.
bool rewriteToObjCLiteralSyntax(const ObjCMessageExpr *Msg, const NSAPI &NS, Commit &commit, const ParentMap *PMap)
static bool hasSuperInitCall(const ObjCMethodDecl *MD)
Definition: ObjCMT.cpp:1693
SourceRange getBraceRange() const
Definition: Decl.h:3141
DominatorTree GraphTraits specialization so the DominatorTree can be iterable by generic graph iterat...
Definition: Dominators.h:30
Stmt - This represents one statement.
Definition: Stmt.h:66
bool insertWrap(StringRef before, CharSourceRange range, StringRef after)
Definition: Commit.cpp:104
SourceLocation getSuperClassLoc() const
Retrieve the starting location of the superclass.
Definition: DeclObjC.cpp:358
Represents the declaration of a typedef-name via the &#39;typedef&#39; type specifier.
Definition: Decl.h:3014
iterator end()
Definition: DeclGroup.h:106
QualType getQualifiedType(SplitQualType split) const
Un-split a SplitQualType.
Definition: ASTContext.h:1932
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:87
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: DeclBase.h:410
StringRef P
const char * getCharacterData(SourceLocation SL, bool *Invalid=nullptr) const
Return a pointer to the start of the specified location in the appropriate spelling MemoryBuffer...
static bool TypeIsInnerPointer(QualType T)
Definition: ObjCMT.cpp:1046
ObjCProtocolDecl * lookupNestedProtocol(IdentifierInfo *Name)
Definition: DeclObjC.cpp:671
DiagnosticsEngine & getDiagnostics() const
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Definition: Diagnostic.h:1294
bool insertAfterToken(SourceLocation loc, StringRef text, bool beforePreviousInsertions=false)
Definition: Commit.h:74
A Range represents the closed range [from, to].
SourceLocation getEndLoc() const LLVM_READONLY
Definition: DeclBase.h:414
A container of type source information.
Definition: Decl.h:86
Parser - This implements a parser for the C family of languages.
Definition: Parser.h:57
bool insertFromRange(SourceLocation loc, CharSourceRange range, bool afterToken=false, bool beforePreviousInsertions=false)
Definition: Commit.cpp:65
ArrayRef< ParmVarDecl * >::const_iterator param_const_iterator
Definition: Decl.h:2259
param_const_iterator param_end() const
Definition: DeclObjC.h:352
SourceLocation getEndLoc() const
Get the end source location.
Definition: TypeLoc.cpp:227
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
Definition: Decl.h:3165
ArrayRef< ArgEffect > getArgs() const
Returns the argument effects for a call.
The argument has its reference count decreased by 1.
enumerator_range enumerators() const
Definition: Decl.h:3449
void removeObjCLifetime()
Definition: Type.h:336
QualType getReturnType() const
Definition: Decl.h:2290
SourceLocation findSemiAfterLocation(SourceLocation loc, ASTContext &Ctx, bool IsDecl=false)
&#39;Loc&#39; is the end of a statement range.
Definition: Transforms.cpp:130
static std::vector< std::string > getWhiteListFilenames(StringRef DirPath)
Definition: ObjCMT.cpp:1988
const T * getAs() const
Member-template getAs<specific type>&#39;.
Definition: Type.h:6716
bool getRawToken(SourceLocation Loc, Token &Result, bool IgnoreWhiteSpace=false)
Relex the token at the specified location.
Abstract interface, implemented by clients of the front-end, which formats and prints fully processed...
Definition: Diagnostic.h:1487
prefer &#39;atomic&#39; property over &#39;nonatomic&#39;.
ObjCMethodDecl - Represents an instance or class method declaration.
Definition: DeclObjC.h:139
RewriteBuffer - As code is rewritten, SourceBuffer&#39;s from the original input with modifications get a...
Definition: RewriteBuffer.h:26
Describes how types, statements, expressions, and declarations should be printed. ...
Definition: PrettyPrinter.h:38
Represents a parameter to a function.
Definition: Decl.h:1551
bool isLiteral() const
Return true if this is a "literal", like a numeric constant, string, etc.
Definition: Token.h:113
The collection of all-type qualifiers we support.
Definition: Type.h:141
static EditEntry getTombstoneKey()
Definition: ObjCMT.cpp:2049
SourceLocation getDeclaratorEndLoc() const
Returns the location where the declarator ends.
Definition: DeclObjC.h:280
annotate property with NS_RETURNS_INNER_POINTER
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition: Decl.h:269
Base wrapper for a particular "section" of type source info.
Definition: TypeLoc.h:57
Expr * IgnoreImpCasts() LLVM_READONLY
IgnoreImpCasts - Skip past any implicit casts which might surround this expression.
Definition: Expr.h:3089
bool insert(SourceLocation loc, StringRef text, bool afterToken=false, bool beforePreviousInsertions=false)
Definition: Commit.cpp:49
SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset=0)
Computes the source location just past the end of the token at this source location.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition: Decl.h:297
instprop_range instance_properties() const
Definition: DeclObjC.h:995
One of these records is kept for each identifier that is lexed.
static ObjCInstanceTypeFamily getInstTypeMethodFamily(Selector sel)
SourceLocation getBegin() const
static std::string applyEditsToTemp(const FileEntry *FE, ArrayRef< EditEntry > Edits, FileManager &FileMgr, DiagnosticsEngine &Diag)
Definition: ObjCMT.cpp:2159
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:154
The results of name lookup within a DeclContext.
Definition: DeclBase.h:1186
const ParmVarDecl *const * param_const_iterator
Definition: DeclObjC.h:343
ObjCMethodFamily
A family of Objective-C methods.
FullExpr - Represents a "full-expression" node.
Definition: Expr.h:876
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:280
bool isObjCIdType() const
Definition: Type.h:6408
Definition: Format.h:2072
Enable migration to modern ObjC literals.
instmeth_range instance_methods() const
Definition: DeclObjC.h:1046
method_range methods() const
Definition: DeclObjC.h:1029
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override
Create the AST consumer object for this action, if supported.
Token - This structure provides full information about a lexed token.
Definition: Token.h:35
bool ReplaceText(SourceLocation Start, unsigned OrigLength, StringRef NewStr)
ReplaceText - This method replaces a range of characters in the input buffer with a new string...
Definition: Rewriter.cpp:307
SourceLocation findLocationAfterSemi(SourceLocation loc, ASTContext &Ctx, bool IsDecl=false)
&#39;Loc&#39; is the end of a statement range.
Definition: Transforms.cpp:118
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:50
IdentifierTable & Idents
Definition: ASTContext.h:565
unsigned SuppressStrongLifetime
When true, suppress printing of the __strong lifetime qualifier in ARC.
static void ReplaceWithInstancetype(ASTContext &Ctx, const ObjCMigrateASTConsumer &ASTC, ObjCMethodDecl *OM)
Definition: ObjCMT.cpp:955
bool isDeprecated(std::string *Message=nullptr) const
Determine whether this declaration is marked &#39;deprecated&#39;.
Definition: DeclBase.h:664
ObjCMethodFamily getMethodFamily() const
Determines the family of this method.
Definition: DeclObjC.cpp:986
bool isInvalid() const
static Selector constructSetterSelector(IdentifierTable &Idents, SelectorTable &SelTable, const IdentifierInfo *Name)
Return the default setter selector for the given identifier.
bool replace(CharSourceRange range, StringRef text)
Definition: Commit.cpp:117
static const char * PropertyMemoryAttribute(ASTContext &Context, QualType ArgType)
Definition: ObjCMT.cpp:426
ObjCContainerDecl - Represents a container for method declarations.
Definition: DeclObjC.h:961
tok::TokenKind getTokenID() const
If this is a source-language token (e.g.
void remap(StringRef filePath, std::unique_ptr< llvm::MemoryBuffer > memBuf)
FrontendOptions & getFrontendOpts()
uint32_t Offset
Definition: CacheTokens.cpp:43
const FormatToken & Tok
static bool UseNSOptionsMacro(Preprocessor &PP, ASTContext &Ctx, const EnumDecl *EnumDcl)
Definition: ObjCMT.cpp:790
static bool rewriteToNSEnumDecl(const EnumDecl *EnumDcl, const TypedefDecl *TypedefDcl, const NSAPI &NS, edit::Commit &commit, StringRef NSIntegerName, bool NSOptions)
Definition: ObjCMT.cpp:705
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Decl.h:2897
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:149
bool BeginInvocation(CompilerInstance &CI) override
Callback before starting processing a single input, giving the opportunity to modify the CompilerInvo...
Definition: ObjCMT.cpp:206
const clang::PrintingPolicy & getPrintingPolicy() const
Definition: ASTContext.h:653
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:3219
Enable migration to NS_ENUM/NS_OPTIONS macros.
iterator begin()
Definition: DeclGroup.h:100
Expr * IgnoreParenCasts() LLVM_READONLY
IgnoreParenCasts - Ignore parentheses and casts.
Definition: Expr.cpp:2579
ObjCProtocolDecl * getDefinition()
Retrieve the definition of this protocol, if any.
Definition: DeclObjC.h:2202
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition: Type.h:6058
static bool reportDiag(const Twine &Err, DiagnosticsEngine &Diag)
Definition: ObjCMT.cpp:2153
child_range children()
Definition: ExprObjC.cpp:345
Represents an Objective-C protocol declaration.
Definition: DeclObjC.h:2056
LLVM_READONLY bool isUppercase(unsigned char c)
Return true if this character is an uppercase ASCII letter: [A-Z].
Definition: CharInfo.h:106
SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)
Returns the results of matching Matcher on Node.
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
Represents an ObjC class declaration.
Definition: DeclObjC.h:1164
QualType getReturnType() const
Definition: DeclObjC.h:323
static EditEntry getEmptyKey()
Definition: ObjCMT.cpp:2044
param_iterator param_begin()
Definition: Decl.h:2262
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
Definition: DeclBase.cpp:1590
const FileEntry * getFile(StringRef Filename, bool OpenFile=false, bool CacheFailure=true)
Lookup, cache, and verify the specified file (real or virtual).
bool hasAttr() const
Definition: DeclBase.h:531
ObjCProtocolDecl * lookupProtocolNamed(IdentifierInfo *PName)
Definition: DeclObjC.cpp:1876
bool flushToFile(StringRef outputPath, DiagnosticsEngine &Diag)
static bool AuditedType(QualType AT)
AuditedType - This routine audits the type AT and returns false if it is one of known CF object types...
Definition: ObjCMT.cpp:1372
bool isValid() const
bool empty() const
Definition: DeclObjC.h:72
SourceLocation getEndLoc() const LLVM_READONLY
Definition: DeclObjC.cpp:980
bool FixupRelativePath(SmallVectorImpl< char > &path) const
If path is not absolute and FileSystemOptions set the working directory, the path is modified to be r...
TypeSourceInfo * getTypeSourceInfo() const
Definition: Decl.h:2962
bool ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl, const ObjCMethodDecl *MethodImp)
LLVM_READONLY bool isIdentifierHead(unsigned char c, bool AllowDollar=false)
Returns true if this is a valid first character of a C identifier, which is [a-zA-Z_].
Definition: CharInfo.h:49
The argument has its reference count increased by 1.
SourceLocation getBeginLoc() const
Get the begin source location.
Definition: TypeLoc.cpp:190
This represents one expression.
Definition: Expr.h:106
SourceLocation End
Represents a character-granular source range.
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
FileID createFileID(const FileEntry *SourceFile, SourceLocation IncludePos, SrcMgr::CharacteristicKind FileCharacter, int LoadedID=0, unsigned LoadedOffset=0)
Create a new FileID that represents the specified file being #included from the specified IncludePosi...
bool isObjCBuiltinType() const
Definition: Type.h:6426
ASTContext & getASTContext() const
Definition: NSAPI.h:28
bool isObjCRetainableType() const
Definition: Type.cpp:3896
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
Definition: DeclBase.h:547
SourceLocation getSelectorStartLoc() const
Definition: DeclObjC.h:289
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file. ...
Definition: Token.h:124
Defines the clang::Preprocessor interface.
StringRef getNameForSlot(unsigned argIndex) const
Retrieve the name at a given position in the selector.
static bool IsCategoryNameWithDeprecatedSuffix(ObjCContainerDecl *D)
Definition: ObjCMT.cpp:563
ObjCInterfaceDecl * getSuperClass() const
Definition: DeclObjC.cpp:338
SourceLocation Begin
Expr ** getArgs()
Retrieve the arguments to this message, not including the receiver.
Definition: ExprObjC.h:1333
Enable migration to add conforming protocols.
ObjCInstanceTypeFamily
A family of Objective-C methods.
IdentifierInfo * getAsIdentifierInfo() const
Retrieve the IdentifierInfo * stored in this declaration name, or null if this declaration name isn&#39;t...
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
Definition: Decl.cpp:2693
protocol_loc_iterator protocol_loc_end() const
Definition: DeclObjC.h:1402
static bool IsValidIdentifier(ASTContext &Ctx, const char *Name)
Definition: ObjCMT.cpp:1144
An expression that sends a message to the given Objective-C object or class.
Definition: ExprObjC.h:904
static bool subscriptOperatorNeedsParens(const Expr *FullExpr)
SourceLocation getEnd() const
bool isInstanceMethod() const
Definition: DeclObjC.h:414
ReceiverKind getReceiverKind() const
Determine the kind of receiver that this message is being sent to.
Definition: ExprObjC.h:1188
int getRangeSize(SourceRange Range, RewriteOptions opts=RewriteOptions()) const
getRangeSize - Return the size in bytes of the specified range if they are in the same file...
Definition: Rewriter.cpp:165
Enable migration to modern ObjC readonly property.
void CollectInheritedProtocols(const Decl *CDecl, llvm::SmallPtrSet< ObjCProtocolDecl *, 8 > &Protocols)
CollectInheritedProtocols - Collect all protocols in current class and those inherited by it...
Selector getSelector() const
Definition: DeclObjC.h:321
ArgEffect
An ArgEffect summarizes the retain count behavior on an argument or receiver to a function or method...
bool isNull() const
Return true if this QualType doesn&#39;t point to a type yet.
Definition: Type.h:707
QualType getType() const
Definition: DeclObjC.h:821
const SourceManager & SM
Definition: Format.cpp:1490
SourceLocation getEndLoc() const LLVM_READONLY
Definition: Stmt.cpp:293
AttrVec & getAttrs()
Definition: DeclBase.h:479
bool hasAttrs() const
Definition: DeclBase.h:473
static CharSourceRange getCharRange(SourceRange R)
SourceManager & getSourceManager() const
Definition: Preprocessor.h:831
TypeSourceInfo * getReturnTypeSourceInfo() const
Definition: DeclObjC.h:337
RecordDecl * getDecl() const
Definition: Type.h:4366
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override
Create the AST consumer object for this action, if supported.
Definition: ObjCMT.cpp:2008
static void ReplaceWithClasstype(const ObjCMigrateASTConsumer &ASTC, ObjCMethodDecl *OM)
Definition: ObjCMT.cpp:978
There is no lifetime qualification on this type.
Definition: Type.h:158
unsigned getNumArgs() const
Return the number of actual arguments in this message, not counting the receiver. ...
Definition: ExprObjC.h:1329
#define false
Definition: stdbool.h:33
LLVM_READONLY char toLowercase(char c)
Converts the given ASCII character to its lowercase equivalent.
Definition: CharInfo.h:165
Assigning into this object requires the old value to be released and the new value to be retained...
Definition: Type.h:169
IdentifierInfo * getIdentifierInfoForSlot(unsigned argIndex) const
Retrieve the identifier at a given position in the selector.
static void append_attr(std::string &PropertyString, const char *attr, bool &LParenAdded)
Definition: ObjCMT.cpp:383
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
Encodes a location in the source.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
raw_ostream & write(raw_ostream &Stream) const
Write to Stream the result of applying all changes to the original buffer.
Definition: Rewriter.cpp:38
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of enums...
Definition: Type.h:4382
StringRef getName() const
Definition: FileManager.h:85
static bool rewriteToObjCInterfaceDecl(const ObjCInterfaceDecl *IDecl, llvm::SmallVectorImpl< ObjCProtocolDecl *> &ConformingProtocols, const NSAPI &NS, edit::Commit &commit)
Definition: ObjCMT.cpp:662
decl_iterator decls_begin() const
Definition: DeclBase.cpp:1374
static unsigned getHashValue(const EditEntry &Val)
Definition: ObjCMT.cpp:2054
bool flushToDisk(StringRef outputDir, DiagnosticsEngine &Diag)
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
Definition: Decl.h:291
Options for controlling the compiler diagnostics engine.
static void MigrateBlockOrFunctionPointerTypeVariable(std::string &PropertyString, const std::string &TypeString, const char *name)
Definition: ObjCMT.cpp:395
ObjCMethodFamily getMethodFamily() const
Definition: ExprObjC.h:1322
Records preprocessor conditional directive regions and allows querying in which region source locatio...
IdentifierTable & getIdentifierTable()
Definition: Preprocessor.h:835
static bool ClassImplementsAllMethodsAndProperties(ASTContext &Ctx, const ObjCImplementationDecl *ImpDecl, const ObjCInterfaceDecl *IDecl, ObjCProtocolDecl *Protocol)
Definition: ObjCMT.cpp:599
Cached information about one file (either on disk or in the virtual file system). ...
Definition: FileManager.h:60
const RewriteBuffer * getRewriteBufferFor(FileID FID) const
getRewriteBufferFor - Return the rewrite buffer for the specified FileID.
Definition: Rewriter.h:172
Stmt * getBody() const override
Retrieve the body of this method, if it has one.
Definition: DeclObjC.cpp:852
bool InsertText(SourceLocation Loc, StringRef Str, bool InsertAfter=true, bool indentNewLines=false)
InsertText - Insert the specified string at the specified location in the original buffer...
Definition: Rewriter.cpp:242
SourceLocation getSuperLoc() const
Retrieve the location of the &#39;super&#39; keyword for a class or instance message to &#39;super&#39;, otherwise an invalid source location.
Definition: ExprObjC.h:1248
ObjCInterfaceDecl * lookupInheritedClass(const IdentifierInfo *ICName)
lookupInheritedClass - This method returns ObjCInterfaceDecl * of the super class whose name is passe...
Definition: DeclObjC.cpp:652
Enable migration to modern ObjC readwrite property.
ObjCCategoryDecl - Represents a category declaration.
Definition: DeclObjC.h:2272
static bool AvailabilityAttrsMatch(Attr *At1, Attr *At2)
AvailabilityAttrsMatch - This routine checks that if comparing two availability attributes, all their components match.
Definition: ObjCMT.cpp:1080
SourceLocation getSelectorLoc(unsigned Index) const
Definition: ExprObjC.h:1372
use NS_NONATOMIC_IOSONLY for property &#39;atomic&#39; attribute
bool isObjCObjectPointerType() const
Definition: Type.h:6379
bool isAnyPointerType() const
Definition: Type.h:6286
MacroDefinition getMacroDefinitionAtLoc(const IdentifierInfo *II, SourceLocation Loc)
Definition: Preprocessor.h:969
Represents one property declaration in an Objective-C interface.
Definition: DeclObjC.h:721
bool isImplicit() const
Indicates whether the message send was implicitly generated by the implementation.
Definition: ExprObjC.h:1184
unsigned getCustomDiagID(Level L, const char(&FormatString)[N])
Return an ID for a diagnostic with the specified format string and level.
Definition: Diagnostic.h:775
const ObjCMethodDecl * getMethodDecl() const
Definition: ExprObjC.h:1303
static StringRef GetUnsignedName(StringRef NSIntegerName)
Definition: ObjCMT.cpp:694
std::map< FileID, RewriteBuffer >::iterator buffer_iterator
Definition: Rewriter.h:55
The argument has its reference count decreased by 1.
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
Definition: ASTContext.h:2292
QualType getObjCInstanceType()
Retrieve the Objective-C "instancetype" type, if already known; otherwise, returns a NULL type;...
Definition: ASTContext.h:1729
Enable annotation of ObjCMethods of all kinds.
bool isRealType() const
Definition: Type.cpp:1935
StringRef getName() const
Return the actual identifier string.
void setIgnoreAllWarnings(bool Val)
When set to true, any unmapped warnings are ignored.
Definition: Diagnostic.h:587
decl_iterator - Iterates through the declarations stored within this context.
Definition: DeclBase.h:1953
Expr * getInstanceReceiver()
Returns the object expression (receiver) for an instance message, or null for a message that is not a...
Definition: ExprObjC.h:1207
ast_type_traits::DynTypedNode Node
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
const ObjCInterfaceDecl * getClassInterface() const
Definition: DeclObjC.h:2432
Dataflow Directional Tag Classes.
bool isValid() const
Return true if this is a valid SourceLocation object.
FileManager & getFileManager() const
Return the current file manager to the caller.
ObjCMigrateAction(std::unique_ptr< FrontendAction > WrappedAction, StringRef migrateDir, unsigned migrateAction)
Definition: ObjCMT.cpp:182
bool isMacroDefined(StringRef Id) const
Returns true if Id is currently defined as a macro.
Definition: NSAPI.cpp:540
static void rewriteToNSMacroDecl(ASTContext &Ctx, const EnumDecl *EnumDcl, const TypedefDecl *TypedefDcl, const NSAPI &NS, edit::Commit &commit, bool IsNSIntegerType)
Definition: ObjCMT.cpp:759
const ObjCProtocolList & getReferencedProtocols() const
Definition: DeclObjC.h:1333
Used for handling and querying diagnostic IDs.
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
Definition: Type.h:975
SourceManager & getSourceManager() const
Return the current source manager.
Represents an enum.
Definition: Decl.h:3322
bool hasObjCLifetime() const
Definition: Type.h:329
unsigned getLength() const
Definition: Token.h:127
param_iterator param_end()
Definition: Decl.h:2263
A frontend action which simply wraps some other runtime-specified frontend action.
bool hasDesignatedInitializers() const
Returns true if this interface decl contains at least one initializer marked with the &#39;objc_designate...
Definition: DeclObjC.cpp:1522
Represents a pointer to an Objective C object.
Definition: Type.h:5780
static bool IsVoidStarType(QualType Ty)
Definition: ObjCMT.cpp:1355
const char * getLiteralData() const
getLiteralData - For a literal token (numeric constant, string, etc), this returns a pointer to the s...
Definition: Token.h:215
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
ObjCImplementationDecl - Represents a class definition - this is where method definitions are specifi...
Definition: DeclObjC.h:2544
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Definition: Type.h:4356
bool hasBody() const override
Determine whether this method has a body.
Definition: DeclObjC.h:496
Enable migration to modern ObjC subscripting.
Enable migration of ObjC methods to &#39;instancetype&#39;.
bool commit(const Commit &commit)
static bool isEqual(const EditEntry &LHS, const EditEntry &RHS)
Definition: ObjCMT.cpp:2062
param_const_iterator param_begin() const
Definition: DeclObjC.h:348
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
Definition: ASTContext.h:2268
SourceLocation getEnd() const
bool getFileRemappingsFromFileList(std::vector< std::pair< std::string, std::string > > &remap, ArrayRef< StringRef > remapFiles, DiagnosticConsumer *DiagClient)
Get the set of file remappings from a list of files with remapping info.
Definition: ObjCMT.cpp:2217
SourceManager & getSourceManager()
Definition: ASTContext.h:661
Keeps track of options that affect how file operations are performed.
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
Definition: ASTContext.h:2252
Enable inferring NS_DESIGNATED_INITIALIZER for ObjC methods.
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
Definition: SemaDecl.cpp:13853
Preprocessor & getPreprocessor() const
Return the current preprocessor.
Reading or writing from this object requires a barrier call.
Definition: Type.h:172
bool initFromDisk(StringRef outputDir, DiagnosticsEngine &Diag, bool ignoreIfFilesChanged)
void applyRewrites(EditsReceiver &receiver, bool adjustRemovals=true)
Rewriter - This is the main interface to the rewrite buffers.
Definition: Rewriter.h:33
const ObjCPropertyDecl * findPropertyDecl(bool CheckOverrides=true) const
Returns the property associated with this method&#39;s selector.
Definition: DeclObjC.cpp:1302
TranslationUnitDecl * getTranslationUnitDecl() const
Definition: ASTContext.h:1008
Enable converting setter/getter expressions to property-dot syntx.
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition: Type.h:6138
ArgEffect getReceiver() const
Returns the effects on the receiver.
ObjCPropertyImplDecl * FindPropertyImplDecl(IdentifierInfo *propertyId, ObjCPropertyQueryKind queryKind) const
FindPropertyImplDecl - This method looks up a previous ObjCPropertyImplDecl added to the list of thos...
Definition: DeclObjC.cpp:2110
bool isVoidType() const
Definition: Type.h:6530
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition: Type.h:6085
static bool versionsMatch(const VersionTuple &X, const VersionTuple &Y)
Check whether the two versions match.
Definition: ObjCMT.cpp:1071
static void rewriteToObjCProperty(const ObjCMethodDecl *Getter, const ObjCMethodDecl *Setter, const NSAPI &NS, edit::Commit &commit, unsigned LengthOfPrefix, bool Atomic, bool UseNsIosOnlyMacro, bool AvailabilityArgsMatch)
Definition: ObjCMT.cpp:452
RetEffect getReturnValue() const
Returns the effect on the return value.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:268
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: DeclObjC.h:283
DiagnosticsEngine & getDiagnostics() const
Get the current diagnostics engine.
QualType getIntegerType() const
Return the integer type this enum decl corresponds to.
Definition: Decl.h:3476
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition: Decl.h:275
bool insertBefore(SourceLocation loc, StringRef text)
Definition: Commit.h:79
static Decl::Kind getKind(const Decl *D)
Definition: DeclBase.cpp:954
The top declaration context.
Definition: Decl.h:107
bool isPointerType() const
Definition: Type.h:6282
StringRef Text
Definition: Format.cpp:1630
QualType getType() const
Definition: Decl.h:647
A trivial tuple used to represent a source range.
ObjCMethodDecl * getMethod(Selector Sel, bool isInstance, bool AllowHidden=false) const
Definition: DeclObjC.cpp:92
ObjCMethodDecl * getInstanceMethod(Selector Sel, bool AllowHidden=false) const
Definition: DeclObjC.h:1079
bool isPropertyAccessor() const
Definition: DeclObjC.h:424
bool isFunctionPointerType() const
Definition: Type.h:6306
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition: Decl.cpp:3042
SourceLocation getBegin() const
const LangOptions & getLangOpts() const
Definition: ASTContext.h:706
ObjCCategoryImplDecl - An object of this class encapsulates a category @implementation declaration...
Definition: DeclObjC.h:2491
void addPPCallbacks(std::unique_ptr< PPCallbacks > C)
Definition: Preprocessor.h:924
This class handles loading and caching of source files into memory.
Attr - This represents one attribute.
Definition: Attr.h:43
SourceLocation getLocation() const
Definition: DeclBase.h:418
QualType getType() const
Return the type wrapped by this type source info.
Definition: Decl.h:97
std::pair< FileID, unsigned > getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Definition: Preprocessor.h:127
decl_iterator decls_end() const
Definition: DeclBase.h:1998
Qualifiers::ObjCLifetime getObjCLifetime() const
Returns lifetime attribute of this type.
Definition: Type.h:1066
RetEffect summarizes a call&#39;s retain/release behavior with respect to its return value.