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