clang  9.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() == ObjKind::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() == ObjKind::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.getKind() == DecRef && AE.getObjKind() == ObjKind::CF &&
1488  !pd->hasAttr<CFConsumedAttr>() &&
1489  NSAPIObj->isMacroDefined("CF_CONSUMED")) {
1490  edit::Commit commit(*Editor);
1491  commit.insertBefore(pd->getLocation(), "CF_CONSUMED ");
1492  Editor->commit(commit);
1493  } else if (AE.getKind() == DecRef && AE.getObjKind() == ObjKind::ObjC &&
1494  !pd->hasAttr<NSConsumedAttr>() &&
1495  NSAPIObj->isMacroDefined("NS_CONSUMED")) {
1496  edit::Commit commit(*Editor);
1497  commit.insertBefore(pd->getLocation(), "NS_CONSUMED ");
1498  Editor->commit(commit);
1499  }
1500  }
1501 }
1502 
1503 ObjCMigrateASTConsumer::CF_BRIDGING_KIND
1504  ObjCMigrateASTConsumer::migrateAddFunctionAnnotation(
1505  ASTContext &Ctx,
1506  const FunctionDecl *FuncDecl) {
1507  if (FuncDecl->hasBody())
1508  return CF_BRIDGING_NONE;
1509 
1510  CallEffects CE = CallEffects::getEffect(FuncDecl);
1511  bool FuncIsReturnAnnotated = (FuncDecl->hasAttr<CFReturnsRetainedAttr>() ||
1512  FuncDecl->hasAttr<CFReturnsNotRetainedAttr>() ||
1513  FuncDecl->hasAttr<NSReturnsRetainedAttr>() ||
1514  FuncDecl->hasAttr<NSReturnsNotRetainedAttr>() ||
1515  FuncDecl->hasAttr<NSReturnsAutoreleasedAttr>());
1516 
1517  // Trivial case of when function is annotated and has no argument.
1518  if (FuncIsReturnAnnotated && FuncDecl->getNumParams() == 0)
1519  return CF_BRIDGING_NONE;
1520 
1521  bool ReturnCFAudited = false;
1522  if (!FuncIsReturnAnnotated) {
1523  RetEffect Ret = CE.getReturnValue();
1524  if (Ret.getObjKind() == ObjKind::CF &&
1525  (Ret.isOwned() || Ret.notOwned()))
1526  ReturnCFAudited = true;
1527  else if (!AuditedType(FuncDecl->getReturnType()))
1528  return CF_BRIDGING_NONE;
1529  }
1530 
1531  // At this point result type is audited for potential inclusion.
1532  // Now, how about argument types.
1533  ArrayRef<ArgEffect> AEArgs = CE.getArgs();
1534  unsigned i = 0;
1535  bool ArgCFAudited = false;
1536  for (FunctionDecl::param_const_iterator pi = FuncDecl->param_begin(),
1537  pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) {
1538  const ParmVarDecl *pd = *pi;
1539  ArgEffect AE = AEArgs[i];
1540  if ((AE.getKind() == DecRef /*CFConsumed annotated*/ ||
1541  AE.getKind() == IncRef) && AE.getObjKind() == ObjKind::CF) {
1542  if (AE.getKind() == DecRef && !pd->hasAttr<CFConsumedAttr>())
1543  ArgCFAudited = true;
1544  else if (AE.getKind() == IncRef)
1545  ArgCFAudited = true;
1546  } else {
1547  QualType AT = pd->getType();
1548  if (!AuditedType(AT)) {
1549  AddCFAnnotations(Ctx, CE, FuncDecl, FuncIsReturnAnnotated);
1550  return CF_BRIDGING_NONE;
1551  }
1552  }
1553  }
1554  if (ReturnCFAudited || ArgCFAudited)
1555  return CF_BRIDGING_ENABLE;
1556 
1557  return CF_BRIDGING_MAY_INCLUDE;
1558 }
1559 
1560 void ObjCMigrateASTConsumer::migrateARCSafeAnnotation(ASTContext &Ctx,
1561  ObjCContainerDecl *CDecl) {
1562  if (!isa<ObjCInterfaceDecl>(CDecl) || CDecl->isDeprecated())
1563  return;
1564 
1565  // migrate methods which can have instancetype as their result type.
1566  for (const auto *Method : CDecl->methods())
1567  migrateCFAnnotation(Ctx, Method);
1568 }
1569 
1570 void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
1571  const CallEffects &CE,
1572  const ObjCMethodDecl *MethodDecl,
1573  bool ResultAnnotated) {
1574  // Annotate function.
1575  if (!ResultAnnotated) {
1576  RetEffect Ret = CE.getReturnValue();
1577  const char *AnnotationString = nullptr;
1578  if (Ret.getObjKind() == ObjKind::CF) {
1579  if (Ret.isOwned() && NSAPIObj->isMacroDefined("CF_RETURNS_RETAINED"))
1580  AnnotationString = " CF_RETURNS_RETAINED";
1581  else if (Ret.notOwned() &&
1582  NSAPIObj->isMacroDefined("CF_RETURNS_NOT_RETAINED"))
1583  AnnotationString = " CF_RETURNS_NOT_RETAINED";
1584  }
1585  else if (Ret.getObjKind() == ObjKind::ObjC) {
1586  ObjCMethodFamily OMF = MethodDecl->getMethodFamily();
1587  switch (OMF) {
1588  case clang::OMF_alloc:
1589  case clang::OMF_new:
1590  case clang::OMF_copy:
1591  case clang::OMF_init:
1593  break;
1594 
1595  default:
1596  if (Ret.isOwned() && NSAPIObj->isMacroDefined("NS_RETURNS_RETAINED"))
1597  AnnotationString = " NS_RETURNS_RETAINED";
1598  break;
1599  }
1600  }
1601 
1602  if (AnnotationString) {
1603  edit::Commit commit(*Editor);
1604  commit.insertBefore(MethodDecl->getEndLoc(), AnnotationString);
1605  Editor->commit(commit);
1606  }
1607  }
1608  ArrayRef<ArgEffect> AEArgs = CE.getArgs();
1609  unsigned i = 0;
1610  for (ObjCMethodDecl::param_const_iterator pi = MethodDecl->param_begin(),
1611  pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) {
1612  const ParmVarDecl *pd = *pi;
1613  ArgEffect AE = AEArgs[i];
1614  if (AE.getKind() == DecRef
1615  && AE.getObjKind() == ObjKind::CF
1616  && !pd->hasAttr<CFConsumedAttr>() &&
1617  NSAPIObj->isMacroDefined("CF_CONSUMED")) {
1618  edit::Commit commit(*Editor);
1619  commit.insertBefore(pd->getLocation(), "CF_CONSUMED ");
1620  Editor->commit(commit);
1621  }
1622  }
1623 }
1624 
1625 void ObjCMigrateASTConsumer::migrateAddMethodAnnotation(
1626  ASTContext &Ctx,
1627  const ObjCMethodDecl *MethodDecl) {
1628  if (MethodDecl->hasBody() || MethodDecl->isImplicit())
1629  return;
1630 
1631  CallEffects CE = CallEffects::getEffect(MethodDecl);
1632  bool MethodIsReturnAnnotated =
1633  (MethodDecl->hasAttr<CFReturnsRetainedAttr>() ||
1634  MethodDecl->hasAttr<CFReturnsNotRetainedAttr>() ||
1635  MethodDecl->hasAttr<NSReturnsRetainedAttr>() ||
1636  MethodDecl->hasAttr<NSReturnsNotRetainedAttr>() ||
1637  MethodDecl->hasAttr<NSReturnsAutoreleasedAttr>());
1638 
1639  if (CE.getReceiver().getKind() == DecRef &&
1640  !MethodDecl->hasAttr<NSConsumesSelfAttr>() &&
1641  MethodDecl->getMethodFamily() != OMF_init &&
1642  MethodDecl->getMethodFamily() != OMF_release &&
1643  NSAPIObj->isMacroDefined("NS_CONSUMES_SELF")) {
1644  edit::Commit commit(*Editor);
1645  commit.insertBefore(MethodDecl->getEndLoc(), " NS_CONSUMES_SELF");
1646  Editor->commit(commit);
1647  }
1648 
1649  // Trivial case of when function is annotated and has no argument.
1650  if (MethodIsReturnAnnotated &&
1651  (MethodDecl->param_begin() == MethodDecl->param_end()))
1652  return;
1653 
1654  if (!MethodIsReturnAnnotated) {
1655  RetEffect Ret = CE.getReturnValue();
1656  if ((Ret.getObjKind() == ObjKind::CF ||
1657  Ret.getObjKind() == ObjKind::ObjC) &&
1658  (Ret.isOwned() || Ret.notOwned())) {
1659  AddCFAnnotations(Ctx, CE, MethodDecl, false);
1660  return;
1661  } else if (!AuditedType(MethodDecl->getReturnType()))
1662  return;
1663  }
1664 
1665  // At this point result type is either annotated or audited.
1666  // Now, how about argument types.
1667  ArrayRef<ArgEffect> AEArgs = CE.getArgs();
1668  unsigned i = 0;
1669  for (ObjCMethodDecl::param_const_iterator pi = MethodDecl->param_begin(),
1670  pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) {
1671  const ParmVarDecl *pd = *pi;
1672  ArgEffect AE = AEArgs[i];
1673  if ((AE.getKind() == DecRef && !pd->hasAttr<CFConsumedAttr>()) ||
1674  AE.getKind() == IncRef || !AuditedType(pd->getType())) {
1675  AddCFAnnotations(Ctx, CE, MethodDecl, MethodIsReturnAnnotated);
1676  return;
1677  }
1678  }
1679 }
1680 
1681 namespace {
1682 class SuperInitChecker : public RecursiveASTVisitor<SuperInitChecker> {
1683 public:
1684  bool shouldVisitTemplateInstantiations() const { return false; }
1685  bool shouldWalkTypesOfTypeLocs() const { return false; }
1686 
1687  bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
1689  if (E->getMethodFamily() == OMF_init)
1690  return false;
1691  }
1692  return true;
1693  }
1694 };
1695 } // end anonymous namespace
1696 
1697 static bool hasSuperInitCall(const ObjCMethodDecl *MD) {
1698  return !SuperInitChecker().TraverseStmt(MD->getBody());
1699 }
1700 
1701 void ObjCMigrateASTConsumer::inferDesignatedInitializers(
1702  ASTContext &Ctx,
1703  const ObjCImplementationDecl *ImplD) {
1704 
1705  const ObjCInterfaceDecl *IFace = ImplD->getClassInterface();
1706  if (!IFace || IFace->hasDesignatedInitializers())
1707  return;
1708  if (!NSAPIObj->isMacroDefined("NS_DESIGNATED_INITIALIZER"))
1709  return;
1710 
1711  for (const auto *MD : ImplD->instance_methods()) {
1712  if (MD->isDeprecated() ||
1713  MD->getMethodFamily() != OMF_init ||
1714  MD->isDesignatedInitializerForTheInterface())
1715  continue;
1716  const ObjCMethodDecl *IFaceM = IFace->getMethod(MD->getSelector(),
1717  /*isInstance=*/true);
1718  if (!IFaceM)
1719  continue;
1720  if (hasSuperInitCall(MD)) {
1721  edit::Commit commit(*Editor);
1722  commit.insert(IFaceM->getEndLoc(), " NS_DESIGNATED_INITIALIZER");
1723  Editor->commit(commit);
1724  }
1725  }
1726 }
1727 
1728 bool ObjCMigrateASTConsumer::InsertFoundation(ASTContext &Ctx,
1729  SourceLocation Loc) {
1730  if (FoundationIncluded)
1731  return true;
1732  if (Loc.isInvalid())
1733  return false;
1734  auto *nsEnumId = &Ctx.Idents.get("NS_ENUM");
1735  if (PP.getMacroDefinitionAtLoc(nsEnumId, Loc)) {
1736  FoundationIncluded = true;
1737  return true;
1738  }
1739  edit::Commit commit(*Editor);
1740  if (Ctx.getLangOpts().Modules)
1741  commit.insert(Loc, "#ifndef NS_ENUM\n@import Foundation;\n#endif\n");
1742  else
1743  commit.insert(Loc, "#ifndef NS_ENUM\n#import <Foundation/Foundation.h>\n#endif\n");
1744  Editor->commit(commit);
1745  FoundationIncluded = true;
1746  return true;
1747 }
1748 
1749 namespace {
1750 
1751 class RewritesReceiver : public edit::EditsReceiver {
1752  Rewriter &Rewrite;
1753 
1754 public:
1755  RewritesReceiver(Rewriter &Rewrite) : Rewrite(Rewrite) { }
1756 
1757  void insert(SourceLocation loc, StringRef text) override {
1758  Rewrite.InsertText(loc, text);
1759  }
1760  void replace(CharSourceRange range, StringRef text) override {
1761  Rewrite.ReplaceText(range.getBegin(), Rewrite.getRangeSize(range), text);
1762  }
1763 };
1764 
1765 class JSONEditWriter : public edit::EditsReceiver {
1766  SourceManager &SourceMgr;
1767  llvm::raw_ostream &OS;
1768 
1769 public:
1770  JSONEditWriter(SourceManager &SM, llvm::raw_ostream &OS)
1771  : SourceMgr(SM), OS(OS) {
1772  OS << "[\n";
1773  }
1774  ~JSONEditWriter() override { OS << "]\n"; }
1775 
1776 private:
1777  struct EntryWriter {
1778  SourceManager &SourceMgr;
1779  llvm::raw_ostream &OS;
1780 
1781  EntryWriter(SourceManager &SM, llvm::raw_ostream &OS)
1782  : SourceMgr(SM), OS(OS) {
1783  OS << " {\n";
1784  }
1785  ~EntryWriter() {
1786  OS << " },\n";
1787  }
1788 
1789  void writeLoc(SourceLocation Loc) {
1790  FileID FID;
1791  unsigned Offset;
1792  std::tie(FID, Offset) = SourceMgr.getDecomposedLoc(Loc);
1793  assert(FID.isValid());
1794  SmallString<200> Path =
1795  StringRef(SourceMgr.getFileEntryForID(FID)->getName());
1796  llvm::sys::fs::make_absolute(Path);
1797  OS << " \"file\": \"";
1798  OS.write_escaped(Path.str()) << "\",\n";
1799  OS << " \"offset\": " << Offset << ",\n";
1800  }
1801 
1802  void writeRemove(CharSourceRange Range) {
1803  assert(Range.isCharRange());
1804  std::pair<FileID, unsigned> Begin =
1805  SourceMgr.getDecomposedLoc(Range.getBegin());
1806  std::pair<FileID, unsigned> End =
1807  SourceMgr.getDecomposedLoc(Range.getEnd());
1808  assert(Begin.first == End.first);
1809  assert(Begin.second <= End.second);
1810  unsigned Length = End.second - Begin.second;
1811 
1812  OS << " \"remove\": " << Length << ",\n";
1813  }
1814 
1815  void writeText(StringRef Text) {
1816  OS << " \"text\": \"";
1817  OS.write_escaped(Text) << "\",\n";
1818  }
1819  };
1820 
1821  void insert(SourceLocation Loc, StringRef Text) override {
1822  EntryWriter Writer(SourceMgr, OS);
1823  Writer.writeLoc(Loc);
1824  Writer.writeText(Text);
1825  }
1826 
1827  void replace(CharSourceRange Range, StringRef Text) override {
1828  EntryWriter Writer(SourceMgr, OS);
1829  Writer.writeLoc(Range.getBegin());
1830  Writer.writeRemove(Range);
1831  Writer.writeText(Text);
1832  }
1833 
1834  void remove(CharSourceRange Range) override {
1835  EntryWriter Writer(SourceMgr, OS);
1836  Writer.writeLoc(Range.getBegin());
1837  Writer.writeRemove(Range);
1838  }
1839 };
1840 
1841 } // end anonymous namespace
1842 
1843 void ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) {
1844 
1846  if (ASTMigrateActions & FrontendOptions::ObjCMT_MigrateDecls) {
1847  for (DeclContext::decl_iterator D = TU->decls_begin(), DEnd = TU->decls_end();
1848  D != DEnd; ++D) {
1849  FileID FID = PP.getSourceManager().getFileID((*D)->getLocation());
1850  if (FID.isValid())
1851  if (FileId.isValid() && FileId != FID) {
1852  if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation)
1853  AnnotateImplicitBridging(Ctx);
1854  }
1855 
1856  if (ObjCInterfaceDecl *CDecl = dyn_cast<ObjCInterfaceDecl>(*D))
1857  if (canModify(CDecl))
1858  migrateObjCContainerDecl(Ctx, CDecl);
1859  if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(*D)) {
1860  if (canModify(CatDecl))
1861  migrateObjCContainerDecl(Ctx, CatDecl);
1862  }
1863  else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(*D)) {
1864  ObjCProtocolDecls.insert(PDecl->getCanonicalDecl());
1865  if (canModify(PDecl))
1866  migrateObjCContainerDecl(Ctx, PDecl);
1867  }
1868  else if (const ObjCImplementationDecl *ImpDecl =
1869  dyn_cast<ObjCImplementationDecl>(*D)) {
1870  if ((ASTMigrateActions & FrontendOptions::ObjCMT_ProtocolConformance) &&
1871  canModify(ImpDecl))
1872  migrateProtocolConformance(Ctx, ImpDecl);
1873  }
1874  else if (const EnumDecl *ED = dyn_cast<EnumDecl>(*D)) {
1875  if (!(ASTMigrateActions & FrontendOptions::ObjCMT_NsMacros))
1876  continue;
1877  if (!canModify(ED))
1878  continue;
1880  if (++N != DEnd) {
1881  const TypedefDecl *TD = dyn_cast<TypedefDecl>(*N);
1882  if (migrateNSEnumDecl(Ctx, ED, TD) && TD)
1883  D++;
1884  }
1885  else
1886  migrateNSEnumDecl(Ctx, ED, /*TypedefDecl */nullptr);
1887  }
1888  else if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(*D)) {
1889  if (!(ASTMigrateActions & FrontendOptions::ObjCMT_NsMacros))
1890  continue;
1891  if (!canModify(TD))
1892  continue;
1894  if (++N == DEnd)
1895  continue;
1896  if (const EnumDecl *ED = dyn_cast<EnumDecl>(*N)) {
1897  if (canModify(ED)) {
1898  if (++N != DEnd)
1899  if (const TypedefDecl *TDF = dyn_cast<TypedefDecl>(*N)) {
1900  // prefer typedef-follows-enum to enum-follows-typedef pattern.
1901  if (migrateNSEnumDecl(Ctx, ED, TDF)) {
1902  ++D; ++D;
1903  CacheObjCNSIntegerTypedefed(TD);
1904  continue;
1905  }
1906  }
1907  if (migrateNSEnumDecl(Ctx, ED, TD)) {
1908  ++D;
1909  continue;
1910  }
1911  }
1912  }
1913  CacheObjCNSIntegerTypedefed(TD);
1914  }
1915  else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*D)) {
1916  if ((ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) &&
1917  canModify(FD))
1918  migrateCFAnnotation(Ctx, FD);
1919  }
1920 
1921  if (ObjCContainerDecl *CDecl = dyn_cast<ObjCContainerDecl>(*D)) {
1922  bool CanModify = canModify(CDecl);
1923  // migrate methods which can have instancetype as their result type.
1924  if ((ASTMigrateActions & FrontendOptions::ObjCMT_Instancetype) &&
1925  CanModify)
1926  migrateAllMethodInstaceType(Ctx, CDecl);
1927  // annotate methods with CF annotations.
1928  if ((ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) &&
1929  CanModify)
1930  migrateARCSafeAnnotation(Ctx, CDecl);
1931  }
1932 
1933  if (const ObjCImplementationDecl *
1934  ImplD = dyn_cast<ObjCImplementationDecl>(*D)) {
1935  if ((ASTMigrateActions & FrontendOptions::ObjCMT_DesignatedInitializer) &&
1936  canModify(ImplD))
1937  inferDesignatedInitializers(Ctx, ImplD);
1938  }
1939  }
1940  if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation)
1941  AnnotateImplicitBridging(Ctx);
1942  }
1943 
1944  if (IsOutputFile) {
1945  std::error_code EC;
1946  llvm::raw_fd_ostream OS(MigrateDir, EC, llvm::sys::fs::F_None);
1947  if (EC) {
1948  DiagnosticsEngine &Diags = Ctx.getDiagnostics();
1949  Diags.Report(Diags.getCustomDiagID(DiagnosticsEngine::Error, "%0"))
1950  << EC.message();
1951  return;
1952  }
1953 
1954  JSONEditWriter Writer(Ctx.getSourceManager(), OS);
1955  Editor->applyRewrites(Writer);
1956  return;
1957  }
1958 
1959  Rewriter rewriter(Ctx.getSourceManager(), Ctx.getLangOpts());
1960  RewritesReceiver Rec(rewriter);
1961  Editor->applyRewrites(Rec);
1962 
1964  I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) {
1965  FileID FID = I->first;
1966  RewriteBuffer &buf = I->second;
1967  const FileEntry *file = Ctx.getSourceManager().getFileEntryForID(FID);
1968  assert(file);
1969  SmallString<512> newText;
1970  llvm::raw_svector_ostream vecOS(newText);
1971  buf.write(vecOS);
1972  std::unique_ptr<llvm::MemoryBuffer> memBuf(
1973  llvm::MemoryBuffer::getMemBufferCopy(
1974  StringRef(newText.data(), newText.size()), file->getName()));
1975  SmallString<64> filePath(file->getName());
1976  FileMgr.FixupRelativePath(filePath);
1977  Remapper.remap(filePath.str(), std::move(memBuf));
1978  }
1979 
1980  if (IsOutputFile) {
1981  Remapper.flushToFile(MigrateDir, Ctx.getDiagnostics());
1982  } else {
1983  Remapper.flushToDisk(MigrateDir, Ctx.getDiagnostics());
1984  }
1985 }
1986 
1989  return true;
1990 }
1991 
1992 static std::vector<std::string> getWhiteListFilenames(StringRef DirPath) {
1993  using namespace llvm::sys::fs;
1994  using namespace llvm::sys::path;
1995 
1996  std::vector<std::string> Filenames;
1997  if (DirPath.empty() || !is_directory(DirPath))
1998  return Filenames;
1999 
2000  std::error_code EC;
2001  directory_iterator DI = directory_iterator(DirPath, EC);
2002  directory_iterator DE;
2003  for (; !EC && DI != DE; DI = DI.increment(EC)) {
2004  if (is_regular_file(DI->path()))
2005  Filenames.push_back(filename(DI->path()));
2006  }
2007 
2008  return Filenames;
2009 }
2010 
2011 std::unique_ptr<ASTConsumer>
2015  unsigned ObjCMTAction = CI.getFrontendOpts().ObjCMTAction;
2016  unsigned ObjCMTOpts = ObjCMTAction;
2017  // These are companion flags, they do not enable transformations.
2018  ObjCMTOpts &= ~(FrontendOptions::ObjCMT_AtomicProperty |
2020  if (ObjCMTOpts == FrontendOptions::ObjCMT_None) {
2021  // If no specific option was given, enable literals+subscripting transforms
2022  // by default.
2023  ObjCMTAction |= FrontendOptions::ObjCMT_Literals |
2025  }
2026  CI.getPreprocessor().addPPCallbacks(std::unique_ptr<PPCallbacks>(PPRec));
2027  std::vector<std::string> WhiteList =
2029  return llvm::make_unique<ObjCMigrateASTConsumer>(
2030  CI.getFrontendOpts().OutputFile, ObjCMTAction, Remapper,
2031  CI.getFileManager(), PPRec, CI.getPreprocessor(),
2032  /*isOutputFile=*/true, WhiteList);
2033 }
2034 
2035 namespace {
2036 struct EditEntry {
2037  const FileEntry *File;
2038  unsigned Offset;
2039  unsigned RemoveLen;
2040  std::string Text;
2041 
2042  EditEntry() : File(), Offset(), RemoveLen() {}
2043 };
2044 } // end anonymous namespace
2045 
2046 namespace llvm {
2047 template<> struct DenseMapInfo<EditEntry> {
2048  static inline EditEntry getEmptyKey() {
2049  EditEntry Entry;
2050  Entry.Offset = unsigned(-1);
2051  return Entry;
2052  }
2053  static inline EditEntry getTombstoneKey() {
2054  EditEntry Entry;
2055  Entry.Offset = unsigned(-2);
2056  return Entry;
2057  }
2058  static unsigned getHashValue(const EditEntry& Val) {
2059  llvm::FoldingSetNodeID ID;
2060  ID.AddPointer(Val.File);
2061  ID.AddInteger(Val.Offset);
2062  ID.AddInteger(Val.RemoveLen);
2063  ID.AddString(Val.Text);
2064  return ID.ComputeHash();
2065  }
2066  static bool isEqual(const EditEntry &LHS, const EditEntry &RHS) {
2067  return LHS.File == RHS.File &&
2068  LHS.Offset == RHS.Offset &&
2069  LHS.RemoveLen == RHS.RemoveLen &&
2070  LHS.Text == RHS.Text;
2071  }
2072 };
2073 } // end namespace llvm
2074 
2075 namespace {
2076 class RemapFileParser {
2077  FileManager &FileMgr;
2078 
2079 public:
2080  RemapFileParser(FileManager &FileMgr) : FileMgr(FileMgr) { }
2081 
2082  bool parse(StringRef File, SmallVectorImpl<EditEntry> &Entries) {
2083  using namespace llvm::yaml;
2084 
2085  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
2086  llvm::MemoryBuffer::getFile(File);
2087  if (!FileBufOrErr)
2088  return true;
2089 
2090  llvm::SourceMgr SM;
2091  Stream YAMLStream(FileBufOrErr.get()->getMemBufferRef(), SM);
2092  document_iterator I = YAMLStream.begin();
2093  if (I == YAMLStream.end())
2094  return true;
2095  Node *Root = I->getRoot();
2096  if (!Root)
2097  return true;
2098 
2099  SequenceNode *SeqNode = dyn_cast<SequenceNode>(Root);
2100  if (!SeqNode)
2101  return true;
2102 
2103  for (SequenceNode::iterator
2104  AI = SeqNode->begin(), AE = SeqNode->end(); AI != AE; ++AI) {
2105  MappingNode *MapNode = dyn_cast<MappingNode>(&*AI);
2106  if (!MapNode)
2107  continue;
2108  parseEdit(MapNode, Entries);
2109  }
2110 
2111  return false;
2112  }
2113 
2114 private:
2115  void parseEdit(llvm::yaml::MappingNode *Node,
2116  SmallVectorImpl<EditEntry> &Entries) {
2117  using namespace llvm::yaml;
2118  EditEntry Entry;
2119  bool Ignore = false;
2120 
2121  for (MappingNode::iterator
2122  KVI = Node->begin(), KVE = Node->end(); KVI != KVE; ++KVI) {
2123  ScalarNode *KeyString = dyn_cast<ScalarNode>((*KVI).getKey());
2124  if (!KeyString)
2125  continue;
2126  SmallString<10> KeyStorage;
2127  StringRef Key = KeyString->getValue(KeyStorage);
2128 
2129  ScalarNode *ValueString = dyn_cast<ScalarNode>((*KVI).getValue());
2130  if (!ValueString)
2131  continue;
2132  SmallString<64> ValueStorage;
2133  StringRef Val = ValueString->getValue(ValueStorage);
2134 
2135  if (Key == "file") {
2136  const FileEntry *FE = FileMgr.getFile(Val);
2137  if (!FE)
2138  Ignore = true;
2139  Entry.File = FE;
2140  } else if (Key == "offset") {
2141  if (Val.getAsInteger(10, Entry.Offset))
2142  Ignore = true;
2143  } else if (Key == "remove") {
2144  if (Val.getAsInteger(10, Entry.RemoveLen))
2145  Ignore = true;
2146  } else if (Key == "text") {
2147  Entry.Text = Val;
2148  }
2149  }
2150 
2151  if (!Ignore)
2152  Entries.push_back(Entry);
2153  }
2154 };
2155 } // end anonymous namespace
2156 
2157 static bool reportDiag(const Twine &Err, DiagnosticsEngine &Diag) {
2159  << Err.str();
2160  return true;
2161 }
2162 
2163 static std::string applyEditsToTemp(const FileEntry *FE,
2164  ArrayRef<EditEntry> Edits,
2165  FileManager &FileMgr,
2167  using namespace llvm::sys;
2168 
2169  SourceManager SM(Diag, FileMgr);
2171  LangOptions LangOpts;
2172  edit::EditedSource Editor(SM, LangOpts);
2174  I = Edits.begin(), E = Edits.end(); I != E; ++I) {
2175  const EditEntry &Entry = *I;
2176  assert(Entry.File == FE);
2177  SourceLocation Loc =
2178  SM.getLocForStartOfFile(FID).getLocWithOffset(Entry.Offset);
2180  if (Entry.RemoveLen != 0) {
2181  Range = CharSourceRange::getCharRange(Loc,
2182  Loc.getLocWithOffset(Entry.RemoveLen));
2183  }
2184 
2185  edit::Commit commit(Editor);
2186  if (Range.isInvalid()) {
2187  commit.insert(Loc, Entry.Text);
2188  } else if (Entry.Text.empty()) {
2189  commit.remove(Range);
2190  } else {
2191  commit.replace(Range, Entry.Text);
2192  }
2193  Editor.commit(commit);
2194  }
2195 
2196  Rewriter rewriter(SM, LangOpts);
2197  RewritesReceiver Rec(rewriter);
2198  Editor.applyRewrites(Rec, /*adjustRemovals=*/false);
2199 
2200  const RewriteBuffer *Buf = rewriter.getRewriteBufferFor(FID);
2201  SmallString<512> NewText;
2202  llvm::raw_svector_ostream OS(NewText);
2203  Buf->write(OS);
2204 
2205  SmallString<64> TempPath;
2206  int FD;
2207  if (fs::createTemporaryFile(path::filename(FE->getName()),
2208  path::extension(FE->getName()).drop_front(), FD,
2209  TempPath)) {
2210  reportDiag("Could not create file: " + TempPath.str(), Diag);
2211  return std::string();
2212  }
2213 
2214  llvm::raw_fd_ostream TmpOut(FD, /*shouldClose=*/true);
2215  TmpOut.write(NewText.data(), NewText.size());
2216  TmpOut.close();
2217 
2218  return TempPath.str();
2219 }
2220 
2222  std::vector<std::pair<std::string,std::string> > &remap,
2223  ArrayRef<StringRef> remapFiles,
2224  DiagnosticConsumer *DiagClient) {
2225  bool hasErrorOccurred = false;
2226 
2227  FileSystemOptions FSOpts;
2228  FileManager FileMgr(FSOpts);
2229  RemapFileParser Parser(FileMgr);
2230 
2233  new DiagnosticsEngine(DiagID, new DiagnosticOptions,
2234  DiagClient, /*ShouldOwnClient=*/false));
2235 
2236  typedef llvm::DenseMap<const FileEntry *, std::vector<EditEntry> >
2237  FileEditEntriesTy;
2238  FileEditEntriesTy FileEditEntries;
2239 
2240  llvm::DenseSet<EditEntry> EntriesSet;
2241 
2243  I = remapFiles.begin(), E = remapFiles.end(); I != E; ++I) {
2245  if (Parser.parse(*I, Entries))
2246  continue;
2247 
2249  EI = Entries.begin(), EE = Entries.end(); EI != EE; ++EI) {
2250  EditEntry &Entry = *EI;
2251  if (!Entry.File)
2252  continue;
2253  std::pair<llvm::DenseSet<EditEntry>::iterator, bool>
2254  Insert = EntriesSet.insert(Entry);
2255  if (!Insert.second)
2256  continue;
2257 
2258  FileEditEntries[Entry.File].push_back(Entry);
2259  }
2260  }
2261 
2262  for (FileEditEntriesTy::iterator
2263  I = FileEditEntries.begin(), E = FileEditEntries.end(); I != E; ++I) {
2264  std::string TempFile = applyEditsToTemp(I->first, I->second,
2265  FileMgr, *Diags);
2266  if (TempFile.empty()) {
2267  hasErrorOccurred = true;
2268  continue;
2269  }
2270 
2271  remap.emplace_back(I->first->getName(), TempFile);
2272  }
2273 
2274  return hasErrorOccurred;
2275 }
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:1987
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:1738
static bool MatchTwoAttributeLists(const AttrVec &Attrs1, const AttrVec &Attrs2, bool &AvailabilityArgsMatch)
Definition: ObjCMT.cpp:1100
Enable migration to modern ObjC readwrite property.
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:825
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition: Type.h:2540
QualType getPointeeType() const
Definition: Type.h:2553
A (possibly-)qualified type.
Definition: Type.h:638
bool isBlockPointerType() const
Definition: Type.h:6307
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:122
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
Enable migration to modern ObjC readonly property.
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:1697
SourceRange getBraceRange() const
Definition: Decl.h:3145
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:3018
use NS_NONATOMIC_IOSONLY for property &#39;atomic&#39; attribute
iterator end()
Definition: DeclGroup.h:106
QualType getQualifiedType(SplitQualType split) const
Un-split a SplitQualType.
Definition: ASTContext.h:1933
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:87
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: DeclBase.h:410
The argument has its reference count increased by 1.
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:1295
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:87
Parser - This implements a parser for the C family of languages.
Definition: Parser.h:58
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:2271
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:3169
ArrayRef< ArgEffect > getArgs() const
Returns the argument effects for a call.
enumerator_range enumerators() const
Definition: Decl.h:3453
void removeObjCLifetime()
Definition: Type.h:332
QualType getReturnType() const
Definition: Decl.h:2302
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:1992
const T * getAs() const
Member-template getAs<specific type>&#39;.
Definition: Type.h:6755
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:1488
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:1550
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:2053
SourceLocation getDeclaratorEndLoc() const
Returns the location where the declarator ends.
Definition: DeclObjC.h:280
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition: Decl.h:270
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:3162
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:298
instprop_range instance_properties() const
Definition: DeclObjC.h:1003
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:2163
Enable migration to modern ObjC literals.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:155
The results of name lookup within a DeclContext.
Definition: DeclBase.h:1187
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:877
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:288
bool isObjCIdType() const
Definition: Type.h:6425
Definition: Format.h:2072
instmeth_range instance_methods() const
Definition: DeclObjC.h:1054
method_range methods() const
Definition: DeclObjC.h:1037
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:566
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
The argument has its reference count decreased by 1.
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:969
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()
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:2901
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:654
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:3287
iterator begin()
Definition: DeclGroup.h:100
Expr * IgnoreParenCasts() LLVM_READONLY
IgnoreParenCasts - Ignore parentheses and casts.
Definition: Expr.cpp:2595
ObjCProtocolDecl * getDefinition()
Retrieve the definition of this protocol, if any.
Definition: DeclObjC.h:2210
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition: Type.h:6075
static bool reportDiag(const Twine &Err, DiagnosticsEngine &Diag)
Definition: ObjCMT.cpp:2157
child_range children()
Definition: ExprObjC.cpp:345
Represents an Objective-C protocol declaration.
Definition: DeclObjC.h:2064
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:1172
QualType getReturnType() const
Definition: DeclObjC.h:323
Enable migration of ObjC methods to &#39;instancetype&#39;.
static EditEntry getEmptyKey()
Definition: ObjCMT.cpp:2048
param_iterator param_begin()
Definition: Decl.h:2274
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
Definition: DeclBase.cpp:1595
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:2966
bool ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl, const ObjCMethodDecl *MethodImp)
Enable migration to add conforming protocols.
unsigned Offset
Definition: Format.cpp:1631
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
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:6443
ASTContext & getASTContext() const
Definition: NSAPI.h:28
bool isObjCRetainableType() const
Definition: Type.cpp:3921
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
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:2695
protocol_loc_iterator protocol_loc_end() const
Definition: DeclObjC.h:1410
Enable annotation of ObjCMethods of all kinds.
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:422
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
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
bool isNull() const
Return true if this QualType doesn&#39;t point to a type yet.
Definition: Type.h:703
QualType getType() const
Definition: DeclObjC.h:829
const SourceManager & SM
Definition: Format.cpp:1490
SourceLocation getEndLoc() const LLVM_READONLY
Definition: Stmt.cpp:301
AttrVec & getAttrs()
Definition: DeclBase.h:479
bool hasAttrs() const
Definition: DeclBase.h:473
static CharSourceRange getCharRange(SourceRange R)
SourceManager & getSourceManager() const
Definition: Preprocessor.h:819
TypeSourceInfo * getReturnTypeSourceInfo() const
Definition: DeclObjC.h:337
RecordDecl * getDecl() const
Definition: Type.h:4383
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override
Create the AST consumer object for this action, if supported.
Definition: ObjCMT.cpp:2012
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
ArgEffectKind getKind() const
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:4399
StringRef getName() const
Definition: FileManager.h:86
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:1371
static unsigned getHashValue(const EditEntry &Val)
Definition: ObjCMT.cpp:2058
prefer &#39;atomic&#39; property over &#39;nonatomic&#39;.
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:292
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:823
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
ObjCCategoryDecl - Represents a category declaration.
Definition: DeclObjC.h:2280
Enable inferring NS_DESIGNATED_INITIALIZER for ObjC methods.
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
annotate property with NS_RETURNS_INNER_POINTER
SourceLocation getSelectorLoc(unsigned Index) const
Definition: ExprObjC.h:1372
bool isObjCObjectPointerType() const
Definition: Type.h:6396
bool isAnyPointerType() const
Definition: Type.h:6303
MacroDefinition getMacroDefinitionAtLoc(const IdentifierInfo *II, SourceLocation Loc)
Definition: Preprocessor.h:953
Enable converting setter/getter expressions to property-dot syntx.
Represents one property declaration in an Objective-C interface.
Definition: DeclObjC.h:729
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:776
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
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
Definition: ASTContext.h:2293
QualType getObjCInstanceType()
Retrieve the Objective-C "instancetype" type, if already known; otherwise, returns a NULL type;...
Definition: ASTContext.h:1730
bool isRealType() const
Definition: Type.cpp:1943
StringRef getName() const
Return the actual identifier string.
void setIgnoreAllWarnings(bool Val)
When set to true, any unmapped warnings are ignored.
Definition: Diagnostic.h:588
decl_iterator - Iterates through the declarations stored within this context.
Definition: DeclBase.h:1954
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:2440
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:1341
Used for handling and querying diagnostic IDs.
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
Definition: Type.h:971
SourceManager & getSourceManager() const
Return the current source manager.
Represents an enum.
Definition: Decl.h:3326
bool hasObjCLifetime() const
Definition: Type.h:325
Enable migration to modern ObjC subscripting.
unsigned getLength() const
Definition: Token.h:127
param_iterator param_end()
Definition: Decl.h:2275
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:5797
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:2552
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Definition: Type.h:4373
Indicates that the tracking object is a descendant of a referenced-counted OSObject, used in the Darwin kernel.
bool hasBody() const override
Determine whether this method has a body.
Definition: DeclObjC.h:504
bool commit(const Commit &commit)
static bool isEqual(const EditEntry &LHS, const EditEntry &RHS)
Definition: ObjCMT.cpp:2066
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:2269
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:2221
SourceManager & getSourceManager()
Definition: ASTContext.h:662
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:2253
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
Definition: SemaDecl.cpp:13954
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:1009
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition: Type.h:6155
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:6547
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition: Type.h:6102
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:276
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:3480
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition: Decl.h:276
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:108
Enable migration to NS_ENUM/NS_OPTIONS macros.
bool isPointerType() const
Definition: Type.h:6299
StringRef Text
Definition: Format.cpp:1630
QualType getType() const
Definition: Decl.h:648
A trivial tuple used to represent a source range.
ObjCMethodDecl * getMethod(Selector Sel, bool isInstance, bool AllowHidden=false) const
Definition: DeclObjC.cpp:92
An ArgEffect summarizes the retain count behavior on an argument or receiver to a function or method...
ObjCMethodDecl * getInstanceMethod(Selector Sel, bool AllowHidden=false) const
Definition: DeclObjC.h:1087
bool isPropertyAccessor() const
Definition: DeclObjC.h:432
bool isFunctionPointerType() const
Definition: Type.h:6323
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Definition: Decl.cpp:3055
SourceLocation getBegin() const
const LangOptions & getLangOpts() const
Definition: ASTContext.h:707
ObjCCategoryImplDecl - An object of this class encapsulates a category @implementation declaration...
Definition: DeclObjC.h:2499
void addPPCallbacks(std::unique_ptr< PPCallbacks > C)
Definition: Preprocessor.h:908
This class handles loading and caching of source files into memory.
Attr - This represents one attribute.
Definition: Attr.h:44
SourceLocation getLocation() const
Definition: DeclBase.h:418
QualType getType() const
Return the type wrapped by this type source info.
Definition: Decl.h:98
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:125
decl_iterator decls_end() const
Definition: DeclBase.h:1999
Qualifiers::ObjCLifetime getObjCLifetime() const
Returns lifetime attribute of this type.
Definition: Type.h:1058
RetEffect summarizes a call&#39;s retain/release behavior with respect to its return value.