clang: lib/ARCMigrate/ObjCMT.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

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

36using namespace clang;

37using namespace arcmt;

38using namespace ento;

39using llvm::RewriteBuffer;

40

41namespace {

42

43class ObjCMigrateASTConsumer : public ASTConsumer {

44 enum CF_BRIDGING_KIND {

45 CF_BRIDGING_NONE,

46 CF_BRIDGING_ENABLE,

47 CF_BRIDGING_MAY_INCLUDE

48 };

49

50 void migrateDecl(Decl *D);

52 void migrateProtocolConformance(ASTContext &Ctx,

54 void CacheObjCNSIntegerTypedefed(const TypedefDecl *TypedefDcl);

66

68 void AddCFAnnotations(ASTContext &Ctx,

70 const FunctionDecl *FuncDecl, bool ResultAnnotated);

71 void AddCFAnnotations(ASTContext &Ctx,

73 const ObjCMethodDecl *MethodDecl, bool ResultAnnotated);

74

75 void AnnotateImplicitBridging(ASTContext &Ctx);

76

77 CF_BRIDGING_KIND migrateAddFunctionAnnotation(ASTContext &Ctx,

79

81

82 void migrateAddMethodAnnotation(ASTContext &Ctx,

84

85 void inferDesignatedInitializers(ASTContext &Ctx,

87

89

90 std::unique_ptr Summaries;

91

92public:

93 std::string MigrateDir;

94 unsigned ASTMigrateActions;

98 std::unique_ptr NSAPIObj;

99 std::unique_ptredit::EditedSource Editor;

104 bool IsOutputFile;

105 bool FoundationIncluded;

108 llvm::StringSet<> AllowListFilenames;

109

111 if (!Summaries)

113 true,

114 false));

115 return *Summaries;

116 }

117

118 ObjCMigrateASTConsumer(StringRef migrateDir, unsigned astMigrateActions,

123 : MigrateDir(migrateDir), ASTMigrateActions(astMigrateActions),

124 NSIntegerTypedefed(nullptr), NSUIntegerTypedefed(nullptr),

125 Remapper(remapper), FileMgr(fileMgr), PPRec(PPRec), PP(PP),

126 IsOutputFile(isOutputFile), FoundationIncluded(false) {

127 AllowListFilenames.insert(AllowList.begin(), AllowList.end());

128 }

129

130protected:

132 NSAPIObj.reset(new NSAPI(Context));

135 PPRec));

136 }

137

140 migrateDecl(*I);

141 return true;

142 }

144

145 }

147 ObjCMigrateASTConsumer::HandleTopLevelDecl(DG);

148 }

149

151

152 bool canModifyFile(StringRef Path) {

153 if (AllowListFilenames.empty())

154 return true;

155 return AllowListFilenames.contains(llvm::sys::path::filename(Path));

156 }

158 if (!FE)

159 return false;

160 return canModifyFile(FE->getName());

161 }

162 bool canModifyFile(FileID FID) {

164 return false;

166 }

167

168 bool canModify(const Decl *D) {

169 if (D)

170 return false;

172 return canModify(CatImpl->getCategoryDecl());

174 return canModify(Impl->getClassInterface());

175 if (const ObjCMethodDecl *MD = dyn_cast(D))

176 return canModify(cast(MD->getDeclContext()));

177

179 return canModifyFile(FID);

180 }

181};

182

183}

184

186 std::unique_ptr WrappedAction, StringRef migrateDir,

187 unsigned migrateAction)

189 ObjCMigAction(migrateAction), CompInst(nullptr) {

190 if (MigrateDir.empty())

191 MigrateDir = ".";

192}

193

194std::unique_ptr

199 std::vector<std::unique_ptr> Consumers;

201 Consumers.push_back(std::make_unique(

202 MigrateDir, ObjCMigAction, Remapper, CompInst->getFileManager(), PPRec,

204 return std::make_unique(std::move(Consumers));

205}

206

209 true);

210 CompInst = &CI;

212 return true;

213}

214

215namespace {

216

219 return !(isa(Expr) || isa(Expr) ||

220 isa(Expr) || isa(Expr) ||

221 isa(Expr) || isa(Expr) ||

222 isa(Expr) ||

223 isa(Expr) ||

224 isa(Expr) || isa(Expr) ||

225 isa(Expr) || isa(Expr) ||

226 isa(Expr) || isa(FullExpr) ||

227 isa(Expr) || isa(Expr));

228 }

229

230

231

232 bool rewriteToPropertyDotSyntax(const ObjCMessageExpr *Msg,

239 return false;

241 if (Receiver->getType()->isObjCBuiltinType())

242 return false;

243

245 if (!Method)

246 return false;

248 return false;

249

251 if (!Prop)

252 return false;

253

255 bool ReceiverIsSuper =

257

259 bool NeedsParen =

261 bool IsGetter = (Msg->getNumArgs() == 0);

262 if (IsGetter) {

263

269 std::string PropertyDotString;

270

271

272 if (NeedsParen) {

274 PropertyDotString = ").";

275 }

276 else

277 PropertyDotString = ".";

278 PropertyDotString += Prop->getName();

279 commit.replace(SpaceRange, PropertyDotString);

280

281

284 } else {

285 if (NeedsParen)

287 std::string PropertyDotString = ".";

288 PropertyDotString += Prop->getName();

289 PropertyDotString += " =";

291 const Expr *RHS = Args[0];

292 if (!RHS)

293 return false;

300

301 if (colon && colon[0] == ':')

302 PropertyDotString += " ";

305

308 }

309 return true;

310 }

311

313 ObjCMigrateASTConsumer &Consumer;

315

316public:

317 ObjCMigrator(ObjCMigrateASTConsumer &consumer, ParentMap &PMap)

318 : Consumer(consumer), PMap(PMap) { }

319

320 bool shouldVisitTemplateInstantiations() const { return false; }

321 bool shouldWalkTypesOfTypeLocs() const { return false; }

322

327 Consumer.Editor->commit(commit);

328 }

329

333 Consumer.Editor->commit(commit);

334 }

335

338 rewriteToPropertyDotSyntax(E, Consumer.PP, *Consumer.NSAPIObj,

339 commit, &PMap);

340 Consumer.Editor->commit(commit);

341 }

342

343 return true;

344 }

345

347

348

350 if (!TraverseStmt(SubStmt))

351 return false;

352

353 return WalkUpFromObjCMessageExpr(E);

354 }

355};

356

358 ObjCMigrateASTConsumer &Consumer;

359 std::unique_ptr PMap;

360

361public:

362 BodyMigrator(ObjCMigrateASTConsumer &consumer) : Consumer(consumer) { }

363

364 bool shouldVisitTemplateInstantiations() const { return false; }

365 bool shouldWalkTypesOfTypeLocs() const { return false; }

366

367 bool TraverseStmt(Stmt *S) {

369 ObjCMigrator(Consumer, *PMap).TraverseStmt(S);

370 return true;

371 }

372};

373}

374

375void ObjCMigrateASTConsumer::migrateDecl(Decl *D) {

376 if (D)

377 return;

378 if (isa(D))

379 return;

380

381 BodyMigrator(*this).TraverseDecl(D);

382}

383

384static void append_attr(std::string &PropertyString, const char *attr,

385 bool &LParenAdded) {

386 if (!LParenAdded) {

387 PropertyString += "(";

388 LParenAdded = true;

389 }

390 else

391 PropertyString += ", ";

392 PropertyString += attr;

393}

394

395static

397 const std::string& TypeString,

398 const char *name) {

399 const char *argPtr = TypeString.c_str();

400 int paren = 0;

401 while (*argPtr) {

402 switch (*argPtr) {

403 case '(':

404 PropertyString += *argPtr;

405 paren++;

406 break;

407 case ')':

408 PropertyString += *argPtr;

409 paren--;

410 break;

411 case '^':

412 case '*':

413 PropertyString += (*argPtr);

414 if (paren == 1) {

415 PropertyString += name;

416 name = "";

417 }

418 break;

419 default:

420 PropertyString += *argPtr;

421 break;

422 }

423 argPtr++;

424 }

425}

426

430 if (RetainableObject &&

435 ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface();

436 if (IDecl &&

438 return "copy";

439 else

440 return "strong";

441 }

443 return "copy";

445

446

447 return "weak";

448 else if (RetainableObject)

450 return nullptr;

451}

452

456 unsigned LengthOfPrefix,

457 bool Atomic, bool UseNsIosOnlyMacro,

458 bool AvailabilityArgsMatch) {

460 bool LParenAdded = false;

461 std::string PropertyString = "@property ";

462 if (UseNsIosOnlyMacro && NS.isMacroDefined("NS_NONATOMIC_IOSONLY")) {

463 PropertyString += "(NS_NONATOMIC_IOSONLY";

464 LParenAdded = true;

465 } else if (Atomic) {

466 PropertyString += "(nonatomic";

467 LParenAdded = true;

468 }

469

470 std::string PropertyNameString = Getter->getNameAsString();

471 StringRef PropertyName(PropertyNameString);

472 if (LengthOfPrefix > 0) {

473 if (!LParenAdded) {

474 PropertyString += "(getter=";

475 LParenAdded = true;

476 }

477 else

478 PropertyString += ", getter=";

479 PropertyString += PropertyNameString;

480 }

481

482 if (!Setter)

483 append_attr(PropertyString, "readonly", LParenAdded);

484

485

486

487

488 if (PropertyName == "target" || PropertyName.contains("delegate") ||

489 PropertyName.contains("dataSource")) {

492 append_attr(PropertyString, "assign", LParenAdded);

493 } else if (!Setter) {

496 append_attr(PropertyString, MemoryManagementAttr, LParenAdded);

497 } else {

501 append_attr(PropertyString, MemoryManagementAttr, LParenAdded);

502 }

503 if (LParenAdded)

504 PropertyString += ')';

507

513 }

514 }

515 PropertyString += " ";

519 std::string TypeString = RT.getAsString(SubPolicy);

520 if (LengthOfPrefix > 0) {

521

522

523 StringRef PropertyNameStringRef(PropertyNameString);

524 PropertyNameStringRef = PropertyNameStringRef.drop_front(LengthOfPrefix);

525 PropertyNameString = std::string(PropertyNameStringRef);

526 bool NoLowering = (isUppercase(PropertyNameString[0]) &&

527 PropertyNameString.size() > 1 &&

529 if (!NoLowering)

530 PropertyNameString[0] = toLowercase(PropertyNameString[0]);

531 }

534 TypeString,

535 PropertyNameString.c_str());

536 else {

537 char LastChar = TypeString[TypeString.size()-1];

538 PropertyString += TypeString;

539 if (LastChar != '*')

540 PropertyString += ' ';

541 PropertyString += PropertyNameString;

542 }

545

549 EndGetterSelectorLoc),

550 PropertyString);

551 if (Setter && AvailabilityArgsMatch) {

553

556

557

558 BeginOfSetterDclLoc = BeginOfSetterDclLoc.getLocWithOffset(-1);

560 }

561}

562

565 StringRef Name = CatDecl->getName();

566 return Name.ends_with("Deprecated");

567 }

568 return false;

569}

570

571void ObjCMigrateASTConsumer::migrateObjCContainerDecl(ASTContext &Ctx,

574 return;

575

576 for (auto *Method : D->methods()) {

578 continue;

579 bool PropertyInferred = migrateProperty(Ctx, D, Method);

580

581

582

583 if (!PropertyInferred ||

586 migrateNsReturnsInnerPointer(Ctx, Method);

587 }

589 return;

590

591 for (auto *Prop : D->instance_properties()) {

594 migratePropertyNsReturnsInnerPointer(Ctx, Prop);

595 }

596}

597

598static bool

603

604

605

606 bool HasAtleastOneRequiredProperty = false;

607 if (const ObjCProtocolDecl *PDecl = Protocol->getDefinition())

608 for (const auto *Property : PDecl->instance_properties()) {

610 continue;

611 HasAtleastOneRequiredProperty = true;

614

615

616

618 Property->getDeclName().getAsIdentifierInfo(),

620 return false;

622 if ((ClassProperty->getPropertyAttributes() !=

623 Property->getPropertyAttributes()) ||

625 return false;

626 } else

627 return false;

628 }

629

630

631

632

633 bool HasAtleastOneRequiredMethod = false;

634 if (const ObjCProtocolDecl *PDecl = Protocol->getDefinition()) {

635 if (PDecl->meth_begin() == PDecl->meth_end())

636 return HasAtleastOneRequiredProperty;

637 for (const auto *MD : PDecl->methods()) {

638 if (MD->isImplicit())

639 continue;

641 continue;

644 return false;

645 bool match = false;

646 HasAtleastOneRequiredMethod = true;

648 if (ObjCMethodDecl *ImpMD = dyn_cast(ND))

651 break;

652 }

654 return false;

655 }

656 }

657 return HasAtleastOneRequiredProperty || HasAtleastOneRequiredMethod;

658}

659

664 std::string ClassString;

667

668 if (Protocols.empty()) {

669 ClassString = '<';

670 for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {

671 ClassString += ConformingProtocols[i]->getNameAsString();

672 if (i != (e-1))

673 ClassString += ", ";

674 }

675 ClassString += "> ";

676 }

677 else {

678 ClassString = ", ";

679 for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {

680 ClassString += ConformingProtocols[i]->getNameAsString();

681 if (i != (e-1))

682 ClassString += ", ";

683 }

685 EndLoc = *PL;

686 }

687

689 return true;

690}

691

693 StringRef UnsignedName = llvm::StringSwitch(NSIntegerName)

694 .Case("int8_t", "uint8_t")

695 .Case("int16_t", "uint16_t")

696 .Case("int32_t", "uint32_t")

697 .Case("NSInteger", "NSUInteger")

698 .Case("int64_t", "uint64_t")

699 .Default(NSIntegerName);

700 return UnsignedName;

701}

702

706 StringRef NSIntegerName,

707 bool NSOptions) {

708 std::string ClassString;

709 if (NSOptions) {

710 ClassString = "typedef NS_OPTIONS(";

712 }

713 else {

714 ClassString = "typedef NS_ENUM(";

715 ClassString += NSIntegerName;

716 }

717 ClassString += ", ";

718

720 ClassString += ')';

722 commit.replace(R, ClassString);

726 if (EndOfEnumDclLoc.isValid()) {

729 }

730 else

731 return false;

732

736 if (EndTypedefDclLoc.isValid()) {

738 commit.remove(TDRange);

739 }

740 else

741 return false;

742

743 EndOfEnumDclLoc =

745 true);

746 if (EndOfEnumDclLoc.isValid()) {

748

749

752 return true;

753 }

754 return false;

755}

756

761 bool IsNSIntegerType) {

763 assert(!DesignatedEnumType.isNull()

764 && "rewriteToNSMacroDecl - underlying enum type is null");

765

767 std::string TypeString = DesignatedEnumType.getAsString(Policy);

768 std::string ClassString = IsNSIntegerType ? "NS_ENUM(" : "NS_OPTIONS(";

769 ClassString += TypeString;

770 ClassString += ", ";

771

773 ClassString += ") ";

776 return;

779 commit.replace(R, ClassString);

780

784

786}

787

790 bool PowerOfTwo = true;

791 bool AllHexdecimalEnumerator = true;

792 uint64_t MaxPowerOfTwoVal = 0;

793 for (auto *Enumerator : EnumDcl->enumerators()) {

794 const Expr *InitExpr = Enumerator->getInitExpr();

795 if (!InitExpr) {

796 PowerOfTwo = false;

797 AllHexdecimalEnumerator = false;

798 continue;

799 }

801 if (const BinaryOperator *BO = dyn_cast(InitExpr))

802 if (BO->isShiftOp() || BO->isBitwiseOp())

803 return true;

804

805 uint64_t EnumVal = Enumerator->getInitVal().getZExtValue();

806 if (PowerOfTwo && EnumVal) {

807 if (!llvm::isPowerOf2_64(EnumVal))

808 PowerOfTwo = false;

809 else if (EnumVal > MaxPowerOfTwoVal)

810 MaxPowerOfTwoVal = EnumVal;

811 }

812 if (AllHexdecimalEnumerator && EnumVal) {

813 bool FoundHexdecimalEnumerator = false;

816 if (!PP.getRawToken(EndLoc, Tok, true))

819 FoundHexdecimalEnumerator =

820 (StringLit[0] == '0' && (toLowercase(StringLit[1]) == 'x'));

821 }

822 if (!FoundHexdecimalEnumerator)

823 AllHexdecimalEnumerator = false;

824 }

825 }

826 return AllHexdecimalEnumerator || (PowerOfTwo && (MaxPowerOfTwoVal > 2));

827}

828

829void ObjCMigrateASTConsumer::migrateProtocolConformance(ASTContext &Ctx,

832 if (!IDecl || ObjCProtocolDecls.empty() || IDecl->isDeprecated())

833 return;

834

835

839

841 if (!ExplicitProtocols.count(ProtDecl))

842 PotentialImplicitProtocols.push_back(ProtDecl);

843

844 if (PotentialImplicitProtocols.empty())

845 return;

846

847

848

849

851 for (unsigned i = 0, e = PotentialImplicitProtocols.size(); i != e; i++)

853 PotentialImplicitProtocols[i]))

854 ConformingProtocols.push_back(PotentialImplicitProtocols[i]);

855

856 if (ConformingProtocols.empty())

857 return;

858

859

860

862 for (unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {

863 bool DropIt = false;

865 for (unsigned i1 = 0, e1 = ConformingProtocols.size(); i1 != e1; i1++) {

867 if (PDecl == TargetPDecl)

868 continue;

871 DropIt = true;

872 break;

873 }

874 }

875 if (!DropIt)

876 MinimalConformingProtocols.push_back(TargetPDecl);

877 }

878 if (MinimalConformingProtocols.empty())

879 return;

882 *NSAPIObj, commit);

883 Editor->commit(commit);

884}

885

886void ObjCMigrateASTConsumer::CacheObjCNSIntegerTypedefed(

888

890 if (NSAPIObj->isObjCNSIntegerType(qt))

891 NSIntegerTypedefed = TypedefDcl;

892 else if (NSAPIObj->isObjCNSUIntegerType(qt))

893 NSUIntegerTypedefed = TypedefDcl;

894}

895

896bool ObjCMigrateASTConsumer::migrateNSEnumDecl(ASTContext &Ctx,

901 return false;

902 if (!TypedefDcl) {

903 if (NSIntegerTypedefed) {

904 TypedefDcl = NSIntegerTypedefed;

905 NSIntegerTypedefed = nullptr;

906 }

907 else if (NSUIntegerTypedefed) {

908 TypedefDcl = NSUIntegerTypedefed;

909 NSUIntegerTypedefed = nullptr;

910 }

911 else

912 return false;

913 FileID FileIdOfTypedefDcl =

915 FileID FileIdOfEnumDcl =

917 if (FileIdOfTypedefDcl != FileIdOfEnumDcl)

918 return false;

919 }

921 return false;

922

924 StringRef NSIntegerName = NSAPIObj->GetNSIntegralKind(qt);

925

926 if (NSIntegerName.empty()) {

927

929 if (EnumTy->getDecl() == EnumDcl) {

931 if (!InsertFoundation(Ctx, TypedefDcl->getBeginLoc()))

932 return false;

934 rewriteToNSMacroDecl(Ctx, EnumDcl, TypedefDcl, *NSAPIObj, commit, !NSOptions);

935 Editor->commit(commit);

936 return true;

937 }

938 }

939 return false;

940 }

941

942

944 if (!InsertFoundation(Ctx, TypedefDcl->getBeginLoc()))

945 return false;

948 commit, NSIntegerName, NSOptions);

949 Editor->commit(commit);

950 return Res;

951}

952

954 const ObjCMigrateASTConsumer &ASTC,

957 return;

958

960 std::string ClassString;

962 TypeLoc TL = TSInfo->getTypeLoc();

964 ClassString = "instancetype";

965 }

966 else {

969 ClassString += " (instancetype)";

970 }

972 commit.replace(R, ClassString);

973 ASTC.Editor->commit(commit);

974}

975

980 std::string ClassString;

982 TypeLoc TL = TSInfo->getTypeLoc();

984 ClassString = std::string(IDecl->getName());

985 ClassString += "*";

986 }

987 }

988 else {

990 ClassString = "+ (";

991 ClassString += IDecl->getName(); ClassString += "*)";

992 }

994 commit.replace(R, ClassString);

995 ASTC.Editor->commit(commit);

996}

997

998void ObjCMigrateASTConsumer::migrateMethodInstanceType(ASTContext &Ctx,

1003

1004 std::string ClassName;

1005 switch (OIT_Family) {

1007 migrateFactoryMethod(Ctx, CDecl, OM);

1008 return;

1010 ClassName = "NSArray";

1011 break;

1013 ClassName = "NSDictionary";

1014 break;

1016 migrateFactoryMethod(Ctx, CDecl, OM, OIT_Singleton);

1017 return;

1021 return;

1024 return;

1025 }

1027 return;

1028

1030 if (!IDecl) {

1031 if (ObjCCategoryDecl *CatDecl = dyn_cast(CDecl))

1032 IDecl = CatDecl->getClassInterface();

1033 else if (ObjCImplDecl *ImpDecl = dyn_cast(CDecl))

1035 }

1036 if (!IDecl ||

1038 migrateFactoryMethod(Ctx, CDecl, OM);

1039 return;

1040 }

1042}

1043

1046 return false;

1050 return false;

1051

1052

1055 T = TD->getDecl()->getUnderlyingType();

1057 return true;

1060 if (UPointeeT->isRecordType()) {

1063 return false;

1064 }

1065 return true;

1066}

1067

1068

1069static bool versionsMatch(const VersionTuple &X, const VersionTuple &Y) {

1070 return (X == Y);

1071}

1072

1073

1074

1075

1076

1077

1079 const AvailabilityAttr *AA1 = dyn_cast(At1);

1080 if (!AA1)

1081 return true;

1082 const AvailabilityAttr *AA2 = cast(At2);

1083

1084 VersionTuple Introduced1 = AA1->getIntroduced();

1085 VersionTuple Deprecated1 = AA1->getDeprecated();

1086 VersionTuple Obsoleted1 = AA1->getObsoleted();

1087 bool IsUnavailable1 = AA1->getUnavailable();

1088 VersionTuple Introduced2 = AA2->getIntroduced();

1089 VersionTuple Deprecated2 = AA2->getDeprecated();

1090 VersionTuple Obsoleted2 = AA2->getObsoleted();

1091 bool IsUnavailable2 = AA2->getUnavailable();

1092 return (versionsMatch(Introduced1, Introduced2) &&

1095 IsUnavailable1 == IsUnavailable2);

1096}

1097

1099 bool &AvailabilityArgsMatch) {

1100

1101 for (unsigned i = 0, e = Attrs1.size(); i != e; i++) {

1102 bool match = false;

1103 for (unsigned j = 0, f = Attrs2.size(); j != f; j++) {

1104

1105

1106

1108 if (AvailabilityArgsMatch)

1111 break;

1112 }

1113 }

1115 return false;

1116 }

1117 return true;

1118}

1119

1120

1121

1122

1123

1124

1125

1126

1128 bool &AvailabilityArgsMatch) {

1130 AvailabilityArgsMatch = (Decl1->hasAttrs() == Decl2->hasAttrs());

1131 return true;

1132 }

1133 AvailabilityArgsMatch = true;

1137 if (match && (Attrs2.size() > Attrs1.size()))

1140}

1141

1143 const char *Name) {

1145 return false;

1146 std::string NameString = Name;

1147 NameString[0] = toLowercase(NameString[0]);

1149 return II->getTokenID() == tok::identifier;

1150}

1151

1152bool ObjCMigrateASTConsumer::migrateProperty(ASTContext &Ctx,

1157 return false;

1158

1161 return false;

1162

1166

1168 return false;

1169

1174 getterName);

1175 ObjCMethodDecl *SetterMethod = D->getInstanceMethod(SetterSelector);

1176 unsigned LengthOfPrefix = 0;

1177 if (!SetterMethod) {

1178

1179 StringRef getterNameString = getterName->getName();

1180 bool IsPrefix = getterNameString.starts_with("is");

1181

1182

1184 return false;

1185 if (IsPrefix || getterNameString.starts_with("get")) {

1186 LengthOfPrefix = (IsPrefix ? 2 : 3);

1187 const char *CGetterName = getterNameString.data() + LengthOfPrefix;

1188

1189

1191 return false;

1192 if (CGetterName[0] && isUppercase(CGetterName[0])) {

1193 getterName = &Ctx.Idents.get(CGetterName);

1194 SetterSelector =

1197 getterName);

1198 SetterMethod = D->getInstanceMethod(SetterSelector);

1199 }

1200 }

1201 }

1202

1203 if (SetterMethod) {

1205 return false;

1206 bool AvailabilityArgsMatch;

1208 AttributesMatch(Method, SetterMethod, AvailabilityArgsMatch))

1209 return false;

1210

1211

1214 return false;

1218 return false;

1221 LengthOfPrefix,

1222 (ASTMigrateActions &

1224 (ASTMigrateActions &

1226 AvailabilityArgsMatch);

1227 Editor->commit(commit);

1228 return true;

1229 }

1231

1232

1235 LengthOfPrefix,

1236 (ASTMigrateActions &

1238 (ASTMigrateActions &

1240 false);

1241 Editor->commit(commit);

1242 return true;

1243 }

1244 return false;

1245}

1246

1247void ObjCMigrateASTConsumer::migrateNsReturnsInnerPointer(ASTContext &Ctx,

1251 OM->hasAttr())

1252 return;

1253

1256 !NSAPIObj->isMacroDefined("NS_RETURNS_INNER_POINTER"))

1257 return;

1258

1261 Editor->commit(commit);

1262}

1263

1264void ObjCMigrateASTConsumer::migratePropertyNsReturnsInnerPointer(ASTContext &Ctx,

1267

1269 !NSAPIObj->isMacroDefined("NS_RETURNS_INNER_POINTER"))

1270 return;

1272 commit.insertBefore(P->getEndLoc(), " NS_RETURNS_INNER_POINTER ");

1273 Editor->commit(commit);

1274}

1275

1276void ObjCMigrateASTConsumer::migrateAllMethodInstaceType(ASTContext &Ctx,

1279 return;

1280

1281

1282 for (auto *Method : CDecl->methods()) {

1284 continue;

1285 migrateMethodInstanceType(Ctx, CDecl, Method);

1286 }

1287}

1288

1289void ObjCMigrateASTConsumer::migrateFactoryMethod(ASTContext &Ctx,

1296 return;

1297

1298

1299

1301 if (!IDecl) {

1302 if (ObjCCategoryDecl *CatDecl = dyn_cast(CDecl))

1303 IDecl = CatDecl->getClassInterface();

1304 else if (ObjCImplDecl *ImpDecl = dyn_cast(CDecl))

1306 }

1307 if (!IDecl)

1308 return;

1309

1310 std::string StringClassName = std::string(IDecl->getName());

1311 StringRef LoweredClassName(StringClassName);

1312 std::string StringLoweredClassName = LoweredClassName.lower();

1313 LoweredClassName = StringLoweredClassName;

1314

1317

1318 if (!MethodIdName)

1319 return;

1320

1321 std::string MethodName = std::string(MethodIdName->getName());

1323 StringRef STRefMethodName(MethodName);

1324 size_t len = 0;

1325 if (STRefMethodName.starts_with("standard"))

1326 len = strlen("standard");

1327 else if (STRefMethodName.starts_with("shared"))

1328 len = strlen("shared");

1329 else if (STRefMethodName.starts_with("default"))

1330 len = strlen("default");

1331 else

1332 return;

1333 MethodName = std::string(STRefMethodName.substr(len));

1334 }

1335 std::string MethodNameSubStr = MethodName.substr(0, 3);

1336 StringRef MethodNamePrefix(MethodNameSubStr);

1337 std::string StringLoweredMethodNamePrefix = MethodNamePrefix.lower();

1338 MethodNamePrefix = StringLoweredMethodNamePrefix;

1339 size_t Ix = LoweredClassName.rfind(MethodNamePrefix);

1340 if (Ix == StringRef::npos)

1341 return;

1342 std::string ClassNamePostfix = std::string(LoweredClassName.substr(Ix));

1343 StringRef LoweredMethodName(MethodName);

1344 std::string StringLoweredMethodName = LoweredMethodName.lower();

1345 LoweredMethodName = StringLoweredMethodName;

1346 if (!LoweredMethodName.starts_with(ClassNamePostfix))

1347 return;

1350 else

1352}

1353

1356 return false;

1357

1358

1361 return true;

1363}

1364

1365

1366

1367

1370 return true;

1371

1374

1375

1377 return false;

1378

1379 return true;

1380}

1381

1382void ObjCMigrateASTConsumer::AnnotateImplicitBridging(ASTContext &Ctx) {

1383 if (CFFunctionIBCandidates.empty())

1384 return;

1385 if (!NSAPIObj->isMacroDefined("CF_IMPLICIT_BRIDGING_ENABLED")) {

1386 CFFunctionIBCandidates.clear();

1388 return;

1389 }

1390

1391 const Decl *FirstFD = CFFunctionIBCandidates[0];

1392 const Decl *LastFD =

1393 CFFunctionIBCandidates[CFFunctionIBCandidates.size()-1];

1394 const char *PragmaString = "\nCF_IMPLICIT_BRIDGING_ENABLED\n\n";

1397 PragmaString = "\n\nCF_IMPLICIT_BRIDGING_DISABLED\n";

1399

1401 if (isa(LastFD)) {

1402

1403

1405

1406 bool Failed = PP.getRawToken(EndLoc, Tok, true);

1407 if (!Failed)

1409 }

1411 Editor->commit(commit);

1413 CFFunctionIBCandidates.clear();

1414}

1415

1416void ObjCMigrateASTConsumer::migrateCFAnnotation(ASTContext &Ctx, const Decl *Decl) {

1418 return;

1419

1420 if (Decl->hasAttr()) {

1421 assert(CFFunctionIBCandidates.empty() &&

1422 "Cannot have audited functions/methods inside user "

1423 "provided CF_IMPLICIT_BRIDGING_ENABLE");

1424 return;

1425 }

1426

1427

1428 if (const FunctionDecl *FuncDecl = dyn_cast(Decl)) {

1429 CF_BRIDGING_KIND AuditKind = migrateAddFunctionAnnotation(Ctx, FuncDecl);

1430 if (AuditKind == CF_BRIDGING_ENABLE) {

1431 CFFunctionIBCandidates.push_back(Decl);

1434 }

1435 else if (AuditKind == CF_BRIDGING_MAY_INCLUDE) {

1436 if (!CFFunctionIBCandidates.empty()) {

1437 CFFunctionIBCandidates.push_back(Decl);

1440 }

1441 }

1442 else

1443 AnnotateImplicitBridging(Ctx);

1444 }

1445 else {

1446 migrateAddMethodAnnotation(Ctx, cast(Decl));

1447 AnnotateImplicitBridging(Ctx);

1448 }

1449}

1450

1451void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,

1454 bool ResultAnnotated) {

1455

1456 if (!ResultAnnotated) {

1458 const char *AnnotationString = nullptr;

1459 if (Ret.getObjKind() == ObjKind::CF) {

1460 if (Ret.isOwned() && NSAPIObj->isMacroDefined("CF_RETURNS_RETAINED"))

1461 AnnotationString = " CF_RETURNS_RETAINED";

1462 else if (Ret.notOwned() &&

1463 NSAPIObj->isMacroDefined("CF_RETURNS_NOT_RETAINED"))

1464 AnnotationString = " CF_RETURNS_NOT_RETAINED";

1465 }

1466 else if (Ret.getObjKind() == ObjKind::ObjC) {

1467 if (Ret.isOwned() && NSAPIObj->isMacroDefined("NS_RETURNS_RETAINED"))

1468 AnnotationString = " NS_RETURNS_RETAINED";

1469 }

1470

1471 if (AnnotationString) {

1474 Editor->commit(commit);

1475 }

1476 }

1477 unsigned i = 0;

1479 pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) {

1483 !pd->hasAttr() &&

1484 NSAPIObj->isMacroDefined("CF_CONSUMED")) {

1487 Editor->commit(commit);

1489 !pd->hasAttr() &&

1490 NSAPIObj->isMacroDefined("NS_CONSUMED")) {

1493 Editor->commit(commit);

1494 }

1495 }

1496}

1497

1498ObjCMigrateASTConsumer::CF_BRIDGING_KIND

1499 ObjCMigrateASTConsumer::migrateAddFunctionAnnotation(

1502 if (FuncDecl->hasBody())

1503 return CF_BRIDGING_NONE;

1504

1506 getSummaryManager(Ctx).getSummary(AnyCall(FuncDecl));

1507 bool FuncIsReturnAnnotated = (FuncDecl->hasAttr() ||

1508 FuncDecl->hasAttr() ||

1509 FuncDecl->hasAttr() ||

1510 FuncDecl->hasAttr() ||

1511 FuncDecl->hasAttr());

1512

1513

1514 if (FuncIsReturnAnnotated && FuncDecl->getNumParams() == 0)

1515 return CF_BRIDGING_NONE;

1516

1517 bool ReturnCFAudited = false;

1518 if (!FuncIsReturnAnnotated) {

1520 if (Ret.getObjKind() == ObjKind::CF &&

1521 (Ret.isOwned() || Ret.notOwned()))

1522 ReturnCFAudited = true;

1524 return CF_BRIDGING_NONE;

1525 }

1526

1527

1528 unsigned i = 0;

1529 bool ArgCFAudited = false;

1531 pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) {

1534 if ((AE.getKind() == DecRef ||

1537 ArgCFAudited = true;

1539 ArgCFAudited = true;

1540 } else {

1543 AddCFAnnotations(Ctx, RS, FuncDecl, FuncIsReturnAnnotated);

1544 return CF_BRIDGING_NONE;

1545 }

1546 }

1547 }

1548 if (ReturnCFAudited || ArgCFAudited)

1549 return CF_BRIDGING_ENABLE;

1550

1551 return CF_BRIDGING_MAY_INCLUDE;

1552}

1553

1554void ObjCMigrateASTConsumer::migrateARCSafeAnnotation(ASTContext &Ctx,

1556 if (!isa(CDecl) || CDecl->isDeprecated())

1557 return;

1558

1559

1560 for (const auto *Method : CDecl->methods())

1561 migrateCFAnnotation(Ctx, Method);

1562}

1563

1564void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,

1567 bool ResultAnnotated) {

1568

1569 if (!ResultAnnotated) {

1571 const char *AnnotationString = nullptr;

1572 if (Ret.getObjKind() == ObjKind::CF) {

1573 if (Ret.isOwned() && NSAPIObj->isMacroDefined("CF_RETURNS_RETAINED"))

1574 AnnotationString = " CF_RETURNS_RETAINED";

1575 else if (Ret.notOwned() &&

1576 NSAPIObj->isMacroDefined("CF_RETURNS_NOT_RETAINED"))

1577 AnnotationString = " CF_RETURNS_NOT_RETAINED";

1578 }

1579 else if (Ret.getObjKind() == ObjKind::ObjC) {

1581 switch (OMF) {

1587 break;

1588

1589 default:

1590 if (Ret.isOwned() && NSAPIObj->isMacroDefined("NS_RETURNS_RETAINED"))

1591 AnnotationString = " NS_RETURNS_RETAINED";

1592 break;

1593 }

1594 }

1595

1596 if (AnnotationString) {

1599 Editor->commit(commit);

1600 }

1601 }

1602 unsigned i = 0;

1604 pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) {

1609 && !pd->hasAttr() &&

1610 NSAPIObj->isMacroDefined("CF_CONSUMED")) {

1613 Editor->commit(commit);

1614 }

1615 }

1616}

1617

1618void ObjCMigrateASTConsumer::migrateAddMethodAnnotation(

1622 return;

1623

1625 getSummaryManager(Ctx).getSummary(AnyCall(MethodDecl));

1626

1627 bool MethodIsReturnAnnotated =

1628 (MethodDecl->hasAttr() ||

1629 MethodDecl->hasAttr() ||

1630 MethodDecl->hasAttr() ||

1631 MethodDecl->hasAttr() ||

1632 MethodDecl->hasAttr());

1633

1635 !MethodDecl->hasAttr() &&

1638 NSAPIObj->isMacroDefined("NS_CONSUMES_SELF")) {

1641 Editor->commit(commit);

1642 }

1643

1644

1645 if (MethodIsReturnAnnotated &&

1647 return;

1648

1649 if (!MethodIsReturnAnnotated) {

1651 if ((Ret.getObjKind() == ObjKind::CF ||

1652 Ret.getObjKind() == ObjKind::ObjC) &&

1653 (Ret.isOwned() || Ret.notOwned())) {

1654 AddCFAnnotations(Ctx, RS, MethodDecl, false);

1655 return;

1657 return;

1658 }

1659

1660

1661 unsigned i = 0;

1663 pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) {

1668 AddCFAnnotations(Ctx, RS, MethodDecl, MethodIsReturnAnnotated);

1669 return;

1670 }

1671 }

1672}

1673

1674namespace {

1676public:

1677 bool shouldVisitTemplateInstantiations() const { return false; }

1678 bool shouldWalkTypesOfTypeLocs() const { return false; }

1679

1682 if (E->getMethodFamily() == OMF_init)

1683 return false;

1684 }

1685 return true;

1686 }

1687};

1688}

1689

1691 return !SuperInitChecker().TraverseStmt(MD->getBody());

1692}

1693

1694void ObjCMigrateASTConsumer::inferDesignatedInitializers(

1697

1700 return;

1701 if (!NSAPIObj->isMacroDefined("NS_DESIGNATED_INITIALIZER"))

1702 return;

1703

1705 if (MD->isDeprecated() ||

1706 MD->getMethodFamily() != OMF_init ||

1707 MD->isDesignatedInitializerForTheInterface())

1708 continue;

1710 true);

1711 if (!IFaceM)

1712 continue;

1715 commit.insert(IFaceM->getEndLoc(), " NS_DESIGNATED_INITIALIZER");

1716 Editor->commit(commit);

1717 }

1718 }

1719}

1720

1721bool ObjCMigrateASTConsumer::InsertFoundation(ASTContext &Ctx,

1723 if (FoundationIncluded)

1724 return true;

1725 if (Loc.isInvalid())

1726 return false;

1727 auto *nsEnumId = &Ctx.Idents.get("NS_ENUM");

1729 FoundationIncluded = true;

1730 return true;

1731 }

1734 commit.insert(Loc, "#ifndef NS_ENUM\n@import Foundation;\n#endif\n");

1735 else

1736 commit.insert(Loc, "#ifndef NS_ENUM\n#import <Foundation/Foundation.h>\n#endif\n");

1737 Editor->commit(commit);

1738 FoundationIncluded = true;

1739 return true;

1740}

1741

1742namespace {

1743

1746

1747public:

1749

1750 void insert(SourceLocation loc, StringRef text) override {

1751 Rewrite.InsertText(loc, text);

1752 }

1753 void replace(CharSourceRange range, StringRef text) override {

1754 Rewrite.ReplaceText(range.getBegin(), Rewrite.getRangeSize(range), text);

1755 }

1756};

1757

1760 llvm::raw_ostream &OS;

1761

1762public:

1763 JSONEditWriter(SourceManager &SM, llvm::raw_ostream &OS)

1764 : SourceMgr(SM), OS(OS) {

1765 OS << "[\n";

1766 }

1767 ~JSONEditWriter() override { OS << "]\n"; }

1768

1769private:

1770 struct EntryWriter {

1772 llvm::raw_ostream &OS;

1773

1775 : SourceMgr(SM), OS(OS) {

1776 OS << " {\n";

1777 }

1778 ~EntryWriter() {

1779 OS << " },\n";

1780 }

1781

1784 unsigned Offset;

1789 llvm::sys::fs::make_absolute(Path);

1790 OS << " \"file\": \"";

1791 OS.write_escaped(Path.str()) << "\",\n";

1792 OS << " \"offset\": " << Offset << ",\n";

1793 }

1794

1796 assert(Range.isCharRange());

1797 std::pair<FileID, unsigned> Begin =

1799 std::pair<FileID, unsigned> End =

1801 assert(Begin.first == End.first);

1802 assert(Begin.second <= End.second);

1803 unsigned Length = End.second - Begin.second;

1804

1805 OS << " \"remove\": " << Length << ",\n";

1806 }

1807

1808 void writeText(StringRef Text) {

1809 OS << " \"text\": \"";

1810 OS.write_escaped(Text) << "\",\n";

1811 }

1812 };

1813

1815 EntryWriter Writer(SourceMgr, OS);

1816 Writer.writeLoc(Loc);

1817 Writer.writeText(Text);

1818 }

1819

1821 EntryWriter Writer(SourceMgr, OS);

1822 Writer.writeLoc(Range.getBegin());

1823 Writer.writeRemove(Range);

1824 Writer.writeText(Text);

1825 }

1826

1828 EntryWriter Writer(SourceMgr, OS);

1829 Writer.writeLoc(Range.getBegin());

1830 Writer.writeRemove(Range);

1831 }

1832};

1833

1834}

1835

1836void ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) {

1837

1841 D != DEnd; ++D) {

1844 if (FileId.isValid() && FileId != FID) {

1846 AnnotateImplicitBridging(Ctx);

1847 }

1848

1850 if (canModify(CDecl))

1851 migrateObjCContainerDecl(Ctx, CDecl);

1852 if (ObjCCategoryDecl *CatDecl = dyn_cast(*D)) {

1853 if (canModify(CatDecl))

1854 migrateObjCContainerDecl(Ctx, CatDecl);

1855 }

1856 else if (ObjCProtocolDecl *PDecl = dyn_cast(*D)) {

1858 if (canModify(PDecl))

1859 migrateObjCContainerDecl(Ctx, PDecl);

1860 }

1862 dyn_cast(*D)) {

1864 canModify(ImpDecl))

1865 migrateProtocolConformance(Ctx, ImpDecl);

1866 }

1867 else if (const EnumDecl *ED = dyn_cast(*D)) {

1869 continue;

1870 if (!canModify(ED))

1871 continue;

1873 if (++N != DEnd) {

1874 const TypedefDecl *TD = dyn_cast(*N);

1875 if (migrateNSEnumDecl(Ctx, ED, TD) && TD)

1876 D++;

1877 }

1878 else

1879 migrateNSEnumDecl(Ctx, ED, nullptr);

1880 }

1881 else if (const TypedefDecl *TD = dyn_cast(*D)) {

1883 continue;

1884 if (!canModify(TD))

1885 continue;

1887 if (++N == DEnd)

1888 continue;

1889 if (const EnumDecl *ED = dyn_cast(*N)) {

1890 if (canModify(ED)) {

1891 if (++N != DEnd)

1892 if (const TypedefDecl *TDF = dyn_cast(*N)) {

1893

1894 if (migrateNSEnumDecl(Ctx, ED, TDF)) {

1895 ++D; ++D;

1896 CacheObjCNSIntegerTypedefed(TD);

1897 continue;

1898 }

1899 }

1900 if (migrateNSEnumDecl(Ctx, ED, TD)) {

1901 ++D;

1902 continue;

1903 }

1904 }

1905 }

1906 CacheObjCNSIntegerTypedefed(TD);

1907 }

1908 else if (const FunctionDecl *FD = dyn_cast(*D)) {

1910 canModify(FD))

1911 migrateCFAnnotation(Ctx, FD);

1912 }

1913

1915 bool CanModify = canModify(CDecl);

1916

1918 CanModify)

1919 migrateAllMethodInstaceType(Ctx, CDecl);

1920

1922 CanModify)

1923 migrateARCSafeAnnotation(Ctx, CDecl);

1924 }

1925

1927 ImplD = dyn_cast(*D)) {

1929 canModify(ImplD))

1930 inferDesignatedInitializers(Ctx, ImplD);

1931 }

1932 }

1934 AnnotateImplicitBridging(Ctx);

1935 }

1936

1937 if (IsOutputFile) {

1938 std::error_code EC;

1939 llvm::raw_fd_ostream OS(MigrateDir, EC, llvm::sys::fs::OF_None);

1940 if (EC) {

1943 << EC.message();

1944 return;

1945 }

1946

1948 Editor->applyRewrites(Writer);

1949 return;

1950 }

1951

1953 RewritesReceiver Rec(rewriter);

1954 Editor->applyRewrites(Rec);

1955

1957 I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) {

1958 FileID FID = I->first;

1959 RewriteBuffer &buf = I->second;

1962 assert(file);

1964 llvm::raw_svector_ostream vecOS(newText);

1965 buf.write(vecOS);

1966 std::unique_ptrllvm::MemoryBuffer memBuf(

1967 llvm::MemoryBuffer::getMemBufferCopy(newText.str(), file->getName()));

1970 Remapper.remap(filePath.str(), std::move(memBuf));

1971 }

1972

1973 if (IsOutputFile) {

1975 } else {

1977 }

1978}

1979

1982 return true;

1983}

1984

1986 using namespace llvm::sys::fs;

1987 using namespace llvm::sys::path;

1988

1989 std::vectorstd::string Filenames;

1990 if (DirPath.empty() || !is_directory(DirPath))

1991 return Filenames;

1992

1993 std::error_code EC;

1994 directory_iterator DI = directory_iterator(DirPath, EC);

1995 directory_iterator DE;

1996 for (; !EC && DI != DE; DI = DI.increment(EC)) {

1997 if (is_regular_file(DI->path()))

1998 Filenames.push_back(std::string(filename(DI->path())));

1999 }

2000

2001 return Filenames;

2002}

2003

2004std::unique_ptr

2009 unsigned ObjCMTOpts = ObjCMTAction;

2010

2014

2015

2016 ObjCMTAction |=

2018 }

2020 std::vectorstd::string AllowList =

2022 return std::make_unique(

2025 true, AllowList);

2026}

2027

2028namespace {

2029struct EditEntry {

2031 unsigned Offset = 0;

2032 unsigned RemoveLen = 0;

2033 std::string Text;

2034};

2035}

2036

2037namespace llvm {

2038template<> struct DenseMapInfo {

2040 EditEntry Entry;

2041 Entry.Offset = unsigned(-1);

2042 return Entry;

2043 }

2045 EditEntry Entry;

2046 Entry.Offset = unsigned(-2);

2047 return Entry;

2048 }

2050 return (unsigned)llvm::hash_combine(Val.File, Val.Offset, Val.RemoveLen,

2051 Val.Text);

2052 }

2053 static bool isEqual(const EditEntry &LHS, const EditEntry &RHS) {

2054 return LHS.File == RHS.File &&

2055 LHS.Offset == RHS.Offset &&

2056 LHS.RemoveLen == RHS.RemoveLen &&

2057 LHS.Text == RHS.Text;

2058 }

2059};

2060}

2061

2062namespace {

2063class RemapFileParser {

2065

2066public:

2067 RemapFileParser(FileManager &FileMgr) : FileMgr(FileMgr) { }

2068

2071

2072 llvm::ErrorOr<std::unique_ptrllvm::MemoryBuffer> FileBufOrErr =

2073 llvm::MemoryBuffer::getFile(File);

2074 if (!FileBufOrErr)

2075 return true;

2076

2077 llvm::SourceMgr SM;

2078 Stream YAMLStream(FileBufOrErr.get()->getMemBufferRef(), SM);

2079 document_iterator I = YAMLStream.begin();

2080 if (I == YAMLStream.end())

2081 return true;

2082 Node *Root = I->getRoot();

2083 if (!Root)

2084 return true;

2085

2086 SequenceNode *SeqNode = dyn_cast(Root);

2087 if (!SeqNode)

2088 return true;

2089

2090 for (SequenceNode::iterator

2091 AI = SeqNode->begin(), AE = SeqNode->end(); AI != AE; ++AI) {

2092 MappingNode *MapNode = dyn_cast(&*AI);

2093 if (!MapNode)

2094 continue;

2095 parseEdit(MapNode, Entries);

2096 }

2097

2098 return false;

2099 }

2100

2101private:

2102 void parseEdit(llvm::yaml::MappingNode *Node,

2105 EditEntry Entry;

2106 bool Ignore = false;

2107

2108 for (MappingNode::iterator

2109 KVI = Node->begin(), KVE = Node->end(); KVI != KVE; ++KVI) {

2110 ScalarNode *KeyString = dyn_cast((*KVI).getKey());

2111 if (!KeyString)

2112 continue;

2114 StringRef Key = KeyString->getValue(KeyStorage);

2115

2116 ScalarNode *ValueString = dyn_cast((*KVI).getValue());

2117 if (!ValueString)

2118 continue;

2120 StringRef Val = ValueString->getValue(ValueStorage);

2121

2122 if (Key == "file") {

2124 Entry.File = File;

2125 else

2126 Ignore = true;

2127 } else if (Key == "offset") {

2128 if (Val.getAsInteger(10, Entry.Offset))

2129 Ignore = true;

2130 } else if (Key == "remove") {

2131 if (Val.getAsInteger(10, Entry.RemoveLen))

2132 Ignore = true;

2133 } else if (Key == "text") {

2134 Entry.Text = std::string(Val);

2135 }

2136 }

2137

2138 if (!Ignore)

2139 Entries.push_back(Entry);

2140 }

2141};

2142}

2143

2146 << Err.str();

2147 return true;

2148}

2149

2154 using namespace llvm::sys;

2155

2161 I = Edits.begin(), E = Edits.end(); I != E; ++I) {

2162 const EditEntry &Entry = *I;

2163 assert(Entry.File == FE);

2165 SM.getLocForStartOfFile(FID).getLocWithOffset(Entry.Offset);

2167 if (Entry.RemoveLen != 0) {

2169 Loc.getLocWithOffset(Entry.RemoveLen));

2170 }

2171

2173 if (Range.isInvalid()) {

2175 } else if (Entry.Text.empty()) {

2177 } else {

2179 }

2180 Editor.commit(commit);

2181 }

2182

2184 RewritesReceiver Rec(rewriter);

2185 Editor.applyRewrites(Rec, false);

2186

2189 llvm::raw_svector_ostream OS(NewText);

2190 Buf->write(OS);

2191

2193 int FD;

2194 if (fs::createTemporaryFile(path::filename(FE.getName()),

2195 path::extension(FE.getName()).drop_front(), FD,

2196 TempPath)) {

2197 reportDiag("Could not create file: " + TempPath.str(), Diag);

2198 return std::string();

2199 }

2200

2201 llvm::raw_fd_ostream TmpOut(FD, true);

2202 TmpOut.write(NewText.data(), NewText.size());

2203 TmpOut.close();

2204

2205 return std::string(TempPath);

2206}

2207

2209 std::vector<std::pairstd::string,std::string > &remap,

2212 bool hasErrorOccurred = false;

2213

2216 RemapFileParser Parser(FileMgr);

2217

2221 DiagClient, false));

2222

2223 typedef llvm::DenseMap<FileEntryRef, std::vector >

2224 FileEditEntriesTy;

2225 FileEditEntriesTy FileEditEntries;

2226

2227 llvm::DenseSet EntriesSet;

2228

2230 I = remapFiles.begin(), E = remapFiles.end(); I != E; ++I) {

2232 if (Parser.parse(*I, Entries))

2233 continue;

2234

2236 EI = Entries.begin(), EE = Entries.end(); EI != EE; ++EI) {

2237 EditEntry &Entry = *EI;

2238 if (!Entry.File)

2239 continue;

2240 std::pair<llvm::DenseSet::iterator, bool>

2241 Insert = EntriesSet.insert(Entry);

2242 if (!Insert.second)

2243 continue;

2244

2245 FileEditEntries[*Entry.File].push_back(Entry);

2246 }

2247 }

2248

2249 for (FileEditEntriesTy::iterator

2250 I = FileEditEntries.begin(), E = FileEditEntries.end(); I != E; ++I) {

2251 std::string TempFile = applyEditsToTemp(I->first, I->second,

2252 FileMgr, *Diags);

2253 if (TempFile.empty()) {

2254 hasErrorOccurred = true;

2255 continue;

2256 }

2257

2258 remap.emplace_back(std::string(I->first.getName()), TempFile);

2259 }

2260

2261 return hasErrorOccurred;

2262}

Defines the clang::ASTContext interface.

static Decl::Kind getKind(const Decl *D)

Defines the clang::FileManager interface and associated types.

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.

static bool IsVoidStarType(QualType Ty)

static bool rewriteToObjCInterfaceDecl(const ObjCInterfaceDecl *IDecl, llvm::SmallVectorImpl< ObjCProtocolDecl * > &ConformingProtocols, const NSAPI &NS, edit::Commit &commit)

static bool AuditedType(QualType AT)

AuditedType - This routine audits the type AT and returns false if it is one of known CF object types...

static bool IsValidIdentifier(ASTContext &Ctx, const char *Name)

static bool reportDiag(const Twine &Err, DiagnosticsEngine &Diag)

static bool AvailabilityAttrsMatch(Attr *At1, Attr *At2)

AvailabilityAttrsMatch - This routine checks that if comparing two availability attributes,...

static const char * PropertyMemoryAttribute(ASTContext &Context, QualType ArgType)

static void ReplaceWithInstancetype(ASTContext &Ctx, const ObjCMigrateASTConsumer &ASTC, ObjCMethodDecl *OM)

static void rewriteToObjCProperty(const ObjCMethodDecl *Getter, const ObjCMethodDecl *Setter, const NSAPI &NS, edit::Commit &commit, unsigned LengthOfPrefix, bool Atomic, bool UseNsIosOnlyMacro, bool AvailabilityArgsMatch)

static bool TypeIsInnerPointer(QualType T)

static StringRef GetUnsignedName(StringRef NSIntegerName)

static bool hasSuperInitCall(const ObjCMethodDecl *MD)

static bool IsCategoryNameWithDeprecatedSuffix(ObjCContainerDecl *D)

static std::string applyEditsToTemp(FileEntryRef FE, ArrayRef< EditEntry > Edits, FileManager &FileMgr, DiagnosticsEngine &Diag)

static bool versionsMatch(const VersionTuple &X, const VersionTuple &Y)

Check whether the two versions match.

static bool AttributesMatch(const Decl *Decl1, const Decl *Decl2, bool &AvailabilityArgsMatch)

AttributesMatch - This routine checks list of attributes for two decls.

static bool rewriteToNSEnumDecl(const EnumDecl *EnumDcl, const TypedefDecl *TypedefDcl, const NSAPI &NS, edit::Commit &commit, StringRef NSIntegerName, bool NSOptions)

static void rewriteToNSMacroDecl(ASTContext &Ctx, const EnumDecl *EnumDcl, const TypedefDecl *TypedefDcl, const NSAPI &NS, edit::Commit &commit, bool IsNSIntegerType)

static bool ClassImplementsAllMethodsAndProperties(ASTContext &Ctx, const ObjCImplementationDecl *ImpDecl, const ObjCInterfaceDecl *IDecl, ObjCProtocolDecl *Protocol)

static void append_attr(std::string &PropertyString, const char *attr, bool &LParenAdded)

static void MigrateBlockOrFunctionPointerTypeVariable(std::string &PropertyString, const std::string &TypeString, const char *name)

static void ReplaceWithClasstype(const ObjCMigrateASTConsumer &ASTC, ObjCMethodDecl *OM)

static std::vector< std::string > getAllowListFilenames(StringRef DirPath)

static bool UseNSOptionsMacro(Preprocessor &PP, ASTContext &Ctx, const EnumDecl *EnumDcl)

static bool MatchTwoAttributeLists(const AttrVec &Attrs1, const AttrVec &Attrs2, bool &AvailabilityArgsMatch)

Defines the clang::Preprocessor interface.

static bool subscriptOperatorNeedsParens(const Expr *FullExpr)

ASTConsumer - This is an abstract interface that should be implemented by clients that read ASTs.

virtual void HandleTranslationUnit(ASTContext &Ctx)

HandleTranslationUnit - This method is called when the ASTs for entire translation unit have been par...

virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef D)

Handle the specified top-level declaration that occurred inside and ObjC container.

virtual bool HandleTopLevelDecl(DeclGroupRef D)

HandleTopLevelDecl - Handle the specified top-level declaration.

virtual void Initialize(ASTContext &Context)

Initialize - This is called to initialize the consumer, providing the ASTContext.

virtual void HandleInterestingDecl(DeclGroupRef D)

HandleInterestingDecl - Handle the specified interesting declaration.

Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...

bool ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl, const ObjCMethodDecl *MethodImp)

SourceManager & getSourceManager()

TranslationUnitDecl * getTranslationUnitDecl() const

CanQualType getCanonicalType(QualType T) const

Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...

bool hasSameType(QualType T1, QualType T2) const

Determine whether the given types T1 and T2 are equivalent.

const LangOptions & getLangOpts() const

QualType getObjCInstanceType()

Retrieve the Objective-C "instancetype" type, if already known; otherwise, returns a NULL type;.

QualType getQualifiedType(SplitQualType split) const

Un-split a SplitQualType.

const clang::PrintingPolicy & getPrintingPolicy() const

bool hasSameUnqualifiedType(QualType T1, QualType T2) const

Determine whether the given types are equivalent after cvr-qualifiers have been removed.

DiagnosticsEngine & getDiagnostics() const

void CollectInheritedProtocols(const Decl *CDecl, llvm::SmallPtrSet< ObjCProtocolDecl *, 8 > &Protocols)

CollectInheritedProtocols - Collect all protocols in current class and those inherited by it.

An instance of this class corresponds to a call.

Attr - This represents one attribute.

A builtin binary operation expression such as "x + y" or "x <= y".

Represents a character-granular source range.

static CharSourceRange getCharRange(SourceRange R)

CompilerInstance - Helper class for managing a single instance of the Clang compiler.

DiagnosticsEngine & getDiagnostics() const

Get the current diagnostics engine.

FileManager & getFileManager() const

Return the current file manager to the caller.

Preprocessor & getPreprocessor() const

Return the current preprocessor.

FrontendOptions & getFrontendOpts()

SourceManager & getSourceManager() const

Return the current source manager.

The results of name lookup within a DeclContext.

decl_iterator - Iterates through the declarations stored within this context.

lookup_result lookup(DeclarationName Name) const

lookup - Find the declarations (if any) with the given Name in this context.

decl_iterator decls_end() const

decl_iterator decls_begin() const

Decl - This represents one declaration (or definition), e.g.

SourceLocation getEndLoc() const LLVM_READONLY

bool isImplicit() const

isImplicit - Indicates whether the declaration was implicitly generated by the implementation.

SourceLocation getLocation() const

bool isDeprecated(std::string *Message=nullptr) const

Determine whether this declaration is marked 'deprecated'.

SourceLocation getBeginLoc() const LLVM_READONLY

IdentifierInfo * getAsIdentifierInfo() const

Retrieve the IdentifierInfo * stored in this declaration name, or null if this declaration name isn't...

Abstract interface, implemented by clients of the front-end, which formats and prints fully processed...

Used for handling and querying diagnostic IDs.

Options for controlling the compiler diagnostics engine.

Concrete class used by the front-end to report problems and issues.

DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)

Issue the message to the client.

unsigned getCustomDiagID(Level L, const char(&FormatString)[N])

Return an ID for a diagnostic with the specified format string and level.

void setIgnoreAllWarnings(bool Val)

When set to true, any unmapped warnings are ignored.

enumerator_range enumerators() const

QualType getIntegerType() const

Return the integer type this enum decl corresponds to.

A helper class that allows the use of isa/cast/dyncast to detect TagType objects of enums.

This represents one expression.

Expr * IgnoreParenCasts() LLVM_READONLY

Skip past any parentheses and casts which might surround this expression until reaching a fixed point...

Expr * IgnoreImpCasts() LLVM_READONLY

Skip past any implicit casts which might surround this expression until reaching a fixed point.

A reference to a FileEntry that includes the name of the file as it was accessed by the FileManager's...

StringRef getName() const

The name of this FileEntry.

An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...

Implements support for file system lookup, file system caching, and directory search management.

OptionalFileEntryRef getOptionalFileRef(StringRef Filename, bool OpenFile=false, bool CacheFailure=true)

Get a FileEntryRef if it exists, without doing anything on error.

bool FixupRelativePath(SmallVectorImpl< char > &path) const

If path is not absolute and FileSystemOptions set the working directory, the path is modified to be r...

Keeps track of options that affect how file operations are performed.

std::string ObjCMTAllowListPath

std::string OutputFile

The output file, if any.

@ ObjCMT_Instancetype

Enable migration of ObjC methods to 'instancetype'.

@ ObjCMT_DesignatedInitializer

Enable inferring NS_DESIGNATED_INITIALIZER for ObjC methods.

@ ObjCMT_Annotation

Enable annotation of ObjCMethods of all kinds.

@ ObjCMT_PropertyDotSyntax

Enable converting setter/getter expressions to property-dot syntx.

@ ObjCMT_ProtocolConformance

Enable migration to add conforming protocols.

@ ObjCMT_NsMacros

Enable migration to NS_ENUM/NS_OPTIONS macros.

@ ObjCMT_AtomicProperty

prefer 'atomic' property over 'nonatomic'.

@ ObjCMT_Literals

Enable migration to modern ObjC literals.

@ ObjCMT_ReadonlyProperty

Enable migration to modern ObjC readonly property.

@ ObjCMT_Subscripting

Enable migration to modern ObjC subscripting.

@ ObjCMT_NsAtomicIOSOnlyProperty

use NS_NONATOMIC_IOSONLY for property 'atomic' attribute

@ ObjCMT_ReadwriteProperty

Enable migration to modern ObjC readwrite property.

@ ObjCMT_ReturnsInnerPointerProperty

annotate property with NS_RETURNS_INNER_POINTER

FullExpr - Represents a "full-expression" node.

Represents a function declaration or definition.

param_iterator param_end()

QualType getReturnType() const

param_iterator param_begin()

ArrayRef< ParmVarDecl * >::const_iterator param_const_iterator

unsigned getNumParams() const

Return the number of parameters this function must have based on its FunctionType.

bool hasBody(const FunctionDecl *&Definition) const

Returns true if the function has a body.

One of these records is kept for each identifier that is lexed.

tok::TokenKind getTokenID() const

If this is a source-language token (e.g.

StringRef getName() const

Return the actual identifier string.

IdentifierInfo & get(StringRef Name)

Return the identifier token info for the specified named identifier.

Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...

bool isMacroDefined(StringRef Id) const

Returns true if Id is currently defined as a macro.

ASTContext & getASTContext() const

This represents a decl that may have a name.

IdentifierInfo * getIdentifier() const

Get the identifier that names this declaration, if there is one.

StringRef getName() const

Get the name of identifier for this declaration as a StringRef.

DeclarationName getDeclName() const

Get the actual, stored name of the declaration, which may be a special name.

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...

ObjCCategoryDecl - Represents a category declaration.

ObjCCategoryImplDecl - An object of this class encapsulates a category @implementation declaration.

ObjCContainerDecl - Represents a container for method declarations.

ObjCMethodDecl * getMethod(Selector Sel, bool isInstance, bool AllowHidden=false) const

method_range methods() const

instmeth_range instance_methods() const

ObjCPropertyImplDecl * FindPropertyImplDecl(IdentifierInfo *propertyId, ObjCPropertyQueryKind queryKind) const

FindPropertyImplDecl - This method looks up a previous ObjCPropertyImplDecl added to the list of thos...

const ObjCInterfaceDecl * getClassInterface() const

ObjCImplementationDecl - Represents a class definition - this is where method definitions are specifi...

Represents an ObjC class declaration.

ObjCInterfaceDecl * lookupInheritedClass(const IdentifierInfo *ICName)

lookupInheritedClass - This method returns ObjCInterfaceDecl * of the super class whose name is passe...

protocol_loc_iterator protocol_loc_end() const

SourceLocation getSuperClassLoc() const

Retrieve the starting location of the superclass.

const ObjCProtocolList & getReferencedProtocols() const

ObjCProtocolDecl * lookupNestedProtocol(IdentifierInfo *Name)

bool hasDesignatedInitializers() const

Returns true if this interface decl contains at least one initializer marked with the 'objc_designate...

ObjCInterfaceDecl * getSuperClass() const

ObjCList - This is a simple template class used to hold various lists of decls etc,...

An expression that sends a message to the given Objective-C object or class.

bool isImplicit() const

Indicates whether the message send was implicitly generated by the implementation.

Expr ** getArgs()

Retrieve the arguments to this message, not including the receiver.

Expr * getInstanceReceiver()

Returns the object expression (receiver) for an instance message, or null for a message that is not a...

SourceLocation getSuperLoc() const

Retrieve the location of the 'super' keyword for a class or instance message to 'super',...

@ SuperInstance

The receiver is the instance of the superclass object.

@ Instance

The receiver is an object instance.

const ObjCMethodDecl * getMethodDecl() const

ReceiverKind getReceiverKind() const

Determine the kind of receiver that this message is being sent to.

SourceLocation getSelectorLoc(unsigned Index) const

unsigned getNumArgs() const

Return the number of actual arguments in this message, not counting the receiver.

ObjCMethodDecl - Represents an instance or class method declaration.

bool hasBody() const override

Determine whether this method has a body.

unsigned param_size() const

bool isPropertyAccessor() const

const ObjCPropertyDecl * findPropertyDecl(bool CheckOverrides=true) const

Returns the property associated with this method's selector.

param_const_iterator param_end() const

SourceLocation getSelectorStartLoc() const

param_const_iterator param_begin() const

Stmt * getBody() const override

Retrieve the body of this method, if it has one.

SourceLocation getEndLoc() const LLVM_READONLY

TypeSourceInfo * getReturnTypeSourceInfo() const

const ParmVarDecl *const * param_const_iterator

SourceLocation getBeginLoc() const LLVM_READONLY

Selector getSelector() const

bool isInstanceMethod() const

ObjCMethodFamily getMethodFamily() const

Determines the family of this method.

QualType getReturnType() const

ObjCInterfaceDecl * getClassInterface()

SourceLocation getDeclaratorEndLoc() const

Returns the location where the declarator ends.

Represents a pointer to an Objective C object.

Represents one property declaration in an Objective-C interface.

Represents an Objective-C protocol declaration.

ObjCProtocolDecl * lookupProtocolNamed(IdentifierInfo *PName)

ObjCProtocolDecl * getCanonicalDecl() override

Retrieves the canonical declaration of this Objective-C protocol.

Records preprocessor conditional directive regions and allows querying in which region source locatio...

Represents a parameter to a function.

Parser - This implements a parser for the C family of languages.

PointerType - C99 6.7.5.1 - Pointer Declarators.

QualType getPointeeType() const

Engages in a tight little dance with the lexer to efficiently preprocess tokens.

MacroDefinition getMacroDefinitionAtLoc(const IdentifierInfo *II, SourceLocation Loc)

void addPPCallbacks(std::unique_ptr< PPCallbacks > C)

SourceManager & getSourceManager() const

IdentifierTable & getIdentifierTable()

bool getRawToken(SourceLocation Loc, Token &Result, bool IgnoreWhiteSpace=false)

Relex the token at the specified location.

SelectorTable & getSelectorTable()

SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset=0)

Computes the source location just past the end of the token at this source location.

A (possibly-)qualified type.

bool isNull() const

Return true if this QualType doesn't point to a type yet.

Qualifiers getQualifiers() const

Retrieve the set of qualifiers applied to this type.

Qualifiers::ObjCLifetime getObjCLifetime() const

Returns lifetime attribute of this type.

QualType getUnqualifiedType() const

Retrieve the unqualified variant of the given type, removing as little sugar as possible.

static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)

The collection of all-type qualifiers we support.

@ OCL_Strong

Assigning into this object requires the old value to be released and the new value to be retained.

@ OCL_None

There is no lifetime qualification on this type.

@ OCL_Weak

Reading or writing from this object requires a barrier call.

void removeObjCLifetime()

bool hasObjCLifetime() const

A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...

RecordDecl * getDecl() const

A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...

Rewriter - This is the main interface to the rewrite buffers.

std::map< FileID, llvm::RewriteBuffer >::iterator buffer_iterator

const llvm::RewriteBuffer * getRewriteBufferFor(FileID FID) const

getRewriteBufferFor - Return the rewrite buffer for the specified FileID.

static Selector constructSetterSelector(IdentifierTable &Idents, SelectorTable &SelTable, const IdentifierInfo *Name)

Return the default setter selector for the given identifier.

Smart pointer class that efficiently represents Objective-C method names.

StringRef getNameForSlot(unsigned argIndex) const

Retrieve the name at a given position in the selector.

const IdentifierInfo * getIdentifierInfoForSlot(unsigned argIndex) const

Retrieve the identifier at a given position in the selector.

static ObjCInstanceTypeFamily getInstTypeMethodFamily(Selector sel)

Encodes a location in the source.

bool isValid() const

Return true if this is a valid SourceLocation object.

SourceLocation getLocWithOffset(IntTy Offset) const

Return a source location with the specified offset from this SourceLocation.

This class handles loading and caching of source files into memory.

FileID getFileID(SourceLocation SpellingLoc) const

Return the FileID for a SourceLocation.

OptionalFileEntryRef getFileEntryRefForID(FileID FID) const

Returns the FileEntryRef for the provided FileID.

const char * getCharacterData(SourceLocation SL, bool *Invalid=nullptr) const

Return a pointer to the start of the specified location in the appropriate spelling MemoryBuffer.

std::pair< FileID, unsigned > getDecomposedLoc(SourceLocation Loc) const

Decompose the specified location into a raw FileID + Offset pair.

A trivial tuple used to represent a source range.

SourceLocation getEnd() const

SourceLocation getBegin() const

Stmt - This represents one statement.

SourceLocation getEndLoc() const LLVM_READONLY

SourceRange getSourceRange() const LLVM_READONLY

SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...

SourceLocation getBeginLoc() const LLVM_READONLY

SourceRange getBraceRange() const

bool isCompleteDefinition() const

Return true if this decl has its body fully specified.

Token - This structure provides full information about a lexed token.

bool isLiteral() const

Return true if this is a "literal", like a numeric constant, string, etc.

SourceLocation getLocation() const

Return a source location identifier for the specified offset in the current file.

unsigned getLength() const

const char * getLiteralData() const

getLiteralData - For a literal token (numeric constant, string, etc), this returns a pointer to the s...

The top declaration context.

SourceLocation getBeginLoc() const LLVM_READONLY

Base wrapper for a particular "section" of type source info.

SourceLocation getEndLoc() const

Get the end source location.

SourceLocation getBeginLoc() const

Get the begin source location.

A container of type source information.

QualType getType() const

Return the type wrapped by this type source info.

bool isBlockPointerType() const

bool isObjCBuiltinType() const

bool isFunctionPointerType() const

bool isPointerType() const

const T * castAs() const

Member-template castAs.

bool isObjCIdType() const

bool isObjCObjectPointerType() const

bool isAnyPointerType() const

const T * getAs() const

Member-template getAs'.

bool isObjCRetainableType() const

Represents the declaration of a typedef-name via the 'typedef' type specifier.

TypeSourceInfo * getTypeSourceInfo() const

A frontend action which simply wraps some other runtime-specified frontend action.

std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override

Create the AST consumer object for this action, if supported.

bool flushToDisk(StringRef outputDir, DiagnosticsEngine &Diag)

bool flushToFile(StringRef outputPath, DiagnosticsEngine &Diag)

void remap(StringRef filePath, std::unique_ptr< llvm::MemoryBuffer > memBuf)

bool initFromDisk(StringRef outputDir, DiagnosticsEngine &Diag, bool ignoreIfFilesChanged)

std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override

Create the AST consumer object for this action, if supported.

bool BeginInvocation(CompilerInstance &CI) override

Callback before starting processing a single input, giving the opportunity to modify the CompilerInvo...

bool BeginInvocation(CompilerInstance &CI) override

Callback before starting processing a single input, giving the opportunity to modify the CompilerInvo...

ObjCMigrateAction(std::unique_ptr< FrontendAction > WrappedAction, StringRef migrateDir, unsigned migrateAction)

std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override

Create the AST consumer object for this action, if supported.

bool insertWrap(StringRef before, CharSourceRange range, StringRef after)

bool insertFromRange(SourceLocation loc, CharSourceRange range, bool afterToken=false, bool beforePreviousInsertions=false)

bool insert(SourceLocation loc, StringRef text, bool afterToken=false, bool beforePreviousInsertions=false)

bool insertAfterToken(SourceLocation loc, StringRef text, bool beforePreviousInsertions=false)

bool remove(CharSourceRange range)

bool insertBefore(SourceLocation loc, StringRef text)

bool replace(CharSourceRange range, StringRef text)

void applyRewrites(EditsReceiver &receiver, bool adjustRemovals=true)

bool commit(const Commit &commit)

An ArgEffect summarizes the retain count behavior on an argument or receiver to a function or method.

ObjKind getObjKind() const

ArgEffectKind getKind() const

A Range represents the closed range [from, to].

RetEffect summarizes a call's retain/release behavior with respect to its return value.

Summary for a function with respect to ownership changes.

ArgEffect getReceiverEffect() const

getReceiverEffect - Returns the effect on the receiver of the call.

RetEffect getRetEffect() const

getRetEffect - Returns the effect on the return value of the call.

ArgEffect getArg(unsigned idx) const

getArg - Return the argument effect on the argument specified by idx (starting from 0).

SourceLocation findLocationAfterSemi(SourceLocation loc, ASTContext &Ctx, bool IsDecl=false)

'Loc' is the end of a statement range.

SourceLocation findSemiAfterLocation(SourceLocation loc, ASTContext &Ctx, bool IsDecl=false)

'Loc' is the end of a statement range.

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.

const internal::VariadicAllOfMatcher< Attr > attr

Matches attributes.

SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)

Returns the results of matching Matcher on Node.

bool rewriteToObjCLiteralSyntax(const ObjCMessageExpr *Msg, const NSAPI &NS, Commit &commit, const ParentMap *PMap)

bool rewriteToObjCSubscriptSyntax(const ObjCMessageExpr *Msg, const NSAPI &NS, Commit &commit)

bool isCFObjectRef(QualType T)

@ IncRef

The argument has its reference count increased by 1.

@ DecRef

The argument has its reference count decreased by 1.

bool Ret(InterpState &S, CodePtr &PC)

RangeSelector range(RangeSelector Begin, RangeSelector End)

DEPRECATED. Use enclose.

ASTEdit remove(RangeSelector S)

Removes the source selected by S.

The JSON file list parser is used to communicate input to InstallAPI.

@ Rewrite

We are substituting template parameters for (typically) other template parameters in order to rewrite...

LLVM_READONLY char toLowercase(char c)

Converts the given ASCII character to its lowercase equivalent.

LLVM_READONLY bool isUppercase(unsigned char c)

Return true if this character is an uppercase ASCII letter: [A-Z].

ObjCMethodFamily

A family of Objective-C methods.

@ Property

The type of a property.

ObjCInstanceTypeFamily

A family of Objective-C methods.

const FunctionProtoType * T

LLVM_READONLY bool isAsciiIdentifierStart(unsigned char c, bool AllowDollar=false)

Returns true if this is a valid first character of a C identifier, which is [a-zA-Z_].

Diagnostic wrappers for TextAPI types for error reporting.

Describes how types, statements, expressions, and declarations should be printed.

unsigned SuppressStrongLifetime

When true, suppress printing of the __strong lifetime qualifier in ARC.

unsigned SuppressLifetimeQualifiers

When true, suppress printing of lifetime qualifier in ARC.

static bool isEqual(const EditEntry &LHS, const EditEntry &RHS)

static EditEntry getTombstoneKey()

static unsigned getHashValue(const EditEntry &Val)

static EditEntry getEmptyKey()