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