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