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" 36 using namespace clang;
37 using namespace arcmt;
43 enum CF_BRIDGING_KIND {
46 CF_BRIDGING_MAY_INCLUDE
49 void migrateDecl(
Decl *D);
51 void migrateProtocolConformance(
ASTContext &Ctx,
53 void CacheObjCNSIntegerTypedefed(
const TypedefDecl *TypedefDcl);
68 const RetainSummary *RS,
71 const RetainSummary *RS,
74 void AnnotateImplicitBridging(
ASTContext &Ctx);
76 CF_BRIDGING_KIND migrateAddFunctionAnnotation(
ASTContext &Ctx,
81 void migrateAddMethodAnnotation(
ASTContext &Ctx,
84 void inferDesignatedInitializers(
ASTContext &Ctx,
89 std::unique_ptr<RetainSummaryManager> Summaries;
92 std::string MigrateDir;
93 unsigned ASTMigrateActions;
97 std::unique_ptr<NSAPI> NSAPIObj;
98 std::unique_ptr<edit::EditedSource> Editor;
104 bool FoundationIncluded;
105 llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ObjCProtocolDecls;
107 llvm::StringSet<> WhiteListFilenames;
109 RetainSummaryManager &getSummaryManager(
ASTContext &Ctx) {
111 Summaries.reset(
new RetainSummaryManager(Ctx,
117 ObjCMigrateASTConsumer(StringRef migrateDir,
118 unsigned astMigrateActions,
125 : MigrateDir(migrateDir),
126 ASTMigrateActions(astMigrateActions),
127 NSIntegerTypedefed(nullptr), NSUIntegerTypedefed(nullptr),
128 Remapper(remapper), FileMgr(fileMgr), PPRec(PPRec), PP(PP),
129 IsOutputFile(isOutputFile),
130 FoundationIncluded(
false){
133 for (
const std::string &Val : WhiteList)
134 WhiteListFilenames.insert(Val);
138 void Initialize(
ASTContext &Context)
override {
139 NSAPIObj.reset(
new NSAPI(Context));
153 void HandleTopLevelDeclInObjCContainer(
DeclGroupRef DG)
override {
154 ObjCMigrateASTConsumer::HandleTopLevelDecl(DG);
157 void HandleTranslationUnit(
ASTContext &Ctx)
override;
159 bool canModifyFile(StringRef Path) {
160 if (WhiteListFilenames.empty())
162 return WhiteListFilenames.find(llvm::sys::path::filename(Path))
163 != WhiteListFilenames.end();
165 bool canModifyFile(
const FileEntry *FE) {
168 return canModifyFile(FE->
getName());
170 bool canModifyFile(
FileID FID) {
176 bool canModify(
const Decl *D) {
180 return canModify(CatImpl->getCategoryDecl());
182 return canModify(Impl->getClassInterface());
184 return canModify(cast<Decl>(MD->getDeclContext()));
187 return canModifyFile(FID);
194 std::unique_ptr<FrontendAction> WrappedAction,
195 StringRef migrateDir,
196 unsigned migrateAction)
198 ObjCMigAction(migrateAction),
200 if (MigrateDir.empty())
204 std::unique_ptr<ASTConsumer>
209 std::vector<std::unique_ptr<ASTConsumer>> Consumers;
211 Consumers.push_back(llvm::make_unique<ObjCMigrateASTConsumer>(
212 MigrateDir, ObjCMigAction, Remapper, CompInst->
getFileManager(), PPRec,
214 return llvm::make_unique<MultiplexConsumer>(std::move(Consumers));
229 return !(isa<ArraySubscriptExpr>(Expr) || isa<CallExpr>(Expr) ||
230 isa<DeclRefExpr>(Expr) || isa<CXXNamedCastExpr>(Expr) ||
231 isa<CXXConstructExpr>(Expr) || isa<CXXThisExpr>(Expr) ||
232 isa<CXXTypeidExpr>(Expr) ||
233 isa<CXXUnresolvedConstructExpr>(Expr) ||
234 isa<ObjCMessageExpr>(Expr) || isa<ObjCPropertyRefExpr>(Expr) ||
235 isa<ObjCProtocolExpr>(Expr) || isa<MemberExpr>(Expr) ||
236 isa<ObjCIvarRefExpr>(Expr) || isa<ParenExpr>(FullExpr) ||
237 isa<ParenListExpr>(Expr) || isa<SizeOfPackExpr>(Expr));
251 if (Receiver->getType()->isObjCBuiltinType())
265 bool ReceiverIsSuper =
279 std::string PropertyDotString;
284 PropertyDotString =
").";
287 PropertyDotString =
".";
288 PropertyDotString += Prop->
getName();
289 commit.
replace(SpaceRange, PropertyDotString);
297 std::string PropertyDotString =
".";
298 PropertyDotString += Prop->
getName();
299 PropertyDotString +=
" =";
301 const Expr *RHS = Args[0];
311 if (colon && colon[0] ==
':')
312 PropertyDotString +=
" ";
314 commit.
replace(Range, PropertyDotString);
323 ObjCMigrateASTConsumer &Consumer;
327 ObjCMigrator(ObjCMigrateASTConsumer &consumer,
ParentMap &PMap)
328 : Consumer(consumer), PMap(PMap) { }
330 bool shouldVisitTemplateInstantiations()
const {
return false; }
331 bool shouldWalkTypesOfTypeLocs()
const {
return false; }
337 Consumer.Editor->commit(commit);
343 Consumer.Editor->commit(commit);
348 rewriteToPropertyDotSyntax(E, Consumer.PP, *Consumer.NSAPIObj,
350 Consumer.Editor->commit(commit);
360 if (!TraverseStmt(SubStmt))
363 return WalkUpFromObjCMessageExpr(E);
368 ObjCMigrateASTConsumer &Consumer;
369 std::unique_ptr<ParentMap> PMap;
372 BodyMigrator(ObjCMigrateASTConsumer &consumer) : Consumer(consumer) { }
374 bool shouldVisitTemplateInstantiations()
const {
return false; }
375 bool shouldWalkTypesOfTypeLocs()
const {
return false; }
377 bool TraverseStmt(
Stmt *S) {
379 ObjCMigrator(Consumer, *PMap).TraverseStmt(S);
385 void ObjCMigrateASTConsumer::migrateDecl(
Decl *D) {
388 if (isa<ObjCMethodDecl>(D))
391 BodyMigrator(*this).TraverseDecl(D);
394 static void append_attr(std::string &PropertyString,
const char *attr,
397 PropertyString +=
"(";
401 PropertyString +=
", ";
402 PropertyString += attr;
407 const std::string& TypeString,
409 const char *argPtr = TypeString.c_str();
414 PropertyString += *argPtr;
418 PropertyString += *argPtr;
423 PropertyString += (*argPtr);
425 PropertyString += name;
430 PropertyString += *argPtr;
440 if (RetainableObject &&
458 else if (RetainableObject)
466 unsigned LengthOfPrefix,
467 bool Atomic,
bool UseNsIosOnlyMacro,
468 bool AvailabilityArgsMatch) {
470 bool LParenAdded =
false;
471 std::string PropertyString =
"@property ";
472 if (UseNsIosOnlyMacro && NS.
isMacroDefined(
"NS_NONATOMIC_IOSONLY")) {
473 PropertyString +=
"(NS_NONATOMIC_IOSONLY";
475 }
else if (!Atomic) {
476 PropertyString +=
"(nonatomic";
481 StringRef PropertyName(PropertyNameString);
482 if (LengthOfPrefix > 0) {
484 PropertyString +=
"(getter=";
488 PropertyString +=
", getter=";
489 PropertyString += PropertyNameString;
493 append_attr(PropertyString,
"readonly", LParenAdded);
498 if (PropertyName.equals(
"target") ||
499 (PropertyName.find(
"delegate") != StringRef::npos) ||
500 (PropertyName.find(
"dataSource") != StringRef::npos)) {
503 append_attr(PropertyString,
"assign", LParenAdded);
504 }
else if (!Setter) {
507 append_attr(PropertyString, MemoryManagementAttr, LParenAdded);
512 append_attr(PropertyString, MemoryManagementAttr, LParenAdded);
515 PropertyString +=
')';
517 if (!isa<TypedefType>(RT)) {
526 PropertyString +=
" ";
529 SubPolicy.SuppressLifetimeQualifiers =
true;
530 std::string TypeString = RT.
getAsString(SubPolicy);
531 if (LengthOfPrefix > 0) {
534 StringRef PropertyNameStringRef(PropertyNameString);
535 PropertyNameStringRef = PropertyNameStringRef.drop_front(LengthOfPrefix);
536 PropertyNameString = PropertyNameStringRef;
537 bool NoLowering = (
isUppercase(PropertyNameString[0]) &&
538 PropertyNameString.size() > 1 &&
541 PropertyNameString[0] =
toLowercase(PropertyNameString[0]);
546 PropertyNameString.c_str());
548 char LastChar = TypeString[TypeString.size()-1];
549 PropertyString += TypeString;
551 PropertyString +=
' ';
552 PropertyString += PropertyNameString;
560 EndGetterSelectorLoc),
562 if (Setter && AvailabilityArgsMatch) {
576 StringRef Name = CatDecl->getName();
577 return Name.endswith(
"Deprecated");
582 void ObjCMigrateASTConsumer::migrateObjCContainerDecl(
ASTContext &Ctx,
587 for (
auto *Method : D->
methods()) {
588 if (Method->isDeprecated())
590 bool PropertyInferred = migrateProperty(Ctx, D, Method);
594 if (!PropertyInferred ||
597 migrateNsReturnsInnerPointer(Ctx, Method);
604 !Prop->isDeprecated())
605 migratePropertyNsReturnsInnerPointer(Ctx, Prop);
617 bool HasAtleastOneRequiredProperty =
false;
619 for (
const auto *
Property : PDecl->instance_properties()) {
622 HasAtleastOneRequiredProperty =
true;
629 Property->getDeclName().getAsIdentifierInfo(),
633 else if (
ObjCPropertyDecl *ClassProperty = dyn_cast<ObjCPropertyDecl>(R[0])) {
634 if ((ClassProperty->getPropertyAttributes()
635 !=
Property->getPropertyAttributes()) ||
646 bool HasAtleastOneRequiredMethod =
false;
648 if (PDecl->meth_begin() == PDecl->meth_end())
649 return HasAtleastOneRequiredProperty;
650 for (
const auto *MD : PDecl->methods()) {
651 if (MD->isImplicit())
659 HasAtleastOneRequiredMethod =
true;
660 for (
unsigned I = 0, N = R.
size(); I != N; ++I)
670 return HasAtleastOneRequiredProperty || HasAtleastOneRequiredMethod;
677 std::string ClassString;
681 if (Protocols.
empty()) {
683 for (
unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
684 ClassString += ConformingProtocols[i]->getNameAsString();
692 for (
unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
693 ClassString += ConformingProtocols[i]->getNameAsString();
706 StringRef UnsignedName = llvm::StringSwitch<StringRef>(NSIntegerName)
707 .Case(
"int8_t",
"uint8_t")
708 .Case(
"int16_t",
"uint16_t")
709 .Case(
"int32_t",
"uint32_t")
710 .Case(
"NSInteger",
"NSUInteger")
711 .Case(
"int64_t",
"uint64_t")
712 .Default(NSIntegerName);
719 StringRef NSIntegerName,
721 std::string ClassString;
723 ClassString =
"typedef NS_OPTIONS(";
727 ClassString =
"typedef NS_ENUM(";
728 ClassString += NSIntegerName;
735 commit.
replace(R, ClassString);
739 if (EndOfEnumDclLoc.
isValid()) {
749 if (EndTypedefDclLoc.
isValid()) {
759 if (EndOfEnumDclLoc.
isValid()) {
774 bool IsNSIntegerType) {
776 assert(!DesignatedEnumType.
isNull()
777 &&
"rewriteToNSMacroDecl - underlying enum type is null");
780 std::string TypeString = DesignatedEnumType.
getAsString(Policy);
781 std::string ClassString = IsNSIntegerType ?
"NS_ENUM(" :
"NS_OPTIONS(";
782 ClassString += TypeString;
792 commit.
replace(R, ClassString);
803 bool PowerOfTwo =
true;
804 bool AllHexdecimalEnumerator =
true;
805 uint64_t MaxPowerOfTwoVal = 0;
807 const Expr *InitExpr = Enumerator->getInitExpr();
810 AllHexdecimalEnumerator =
false;
814 if (
const BinaryOperator *BO = dyn_cast<BinaryOperator>(InitExpr))
815 if (BO->isShiftOp() || BO->isBitwiseOp())
818 uint64_t EnumVal = Enumerator->getInitVal().getZExtValue();
819 if (PowerOfTwo && EnumVal) {
820 if (!llvm::isPowerOf2_64(EnumVal))
822 else if (EnumVal > MaxPowerOfTwoVal)
823 MaxPowerOfTwoVal = EnumVal;
825 if (AllHexdecimalEnumerator && EnumVal) {
826 bool FoundHexdecimalEnumerator =
false;
832 FoundHexdecimalEnumerator =
833 (StringLit[0] ==
'0' && (
toLowercase(StringLit[1]) ==
'x'));
835 if (!FoundHexdecimalEnumerator)
836 AllHexdecimalEnumerator =
false;
839 return AllHexdecimalEnumerator || (PowerOfTwo && (MaxPowerOfTwoVal > 2));
842 void ObjCMigrateASTConsumer::migrateProtocolConformance(
ASTContext &Ctx,
845 if (!IDecl || ObjCProtocolDecls.empty() || IDecl->
isDeprecated())
849 llvm::SmallPtrSet<ObjCProtocolDecl *, 8> ExplicitProtocols;
854 if (!ExplicitProtocols.count(ProtDecl))
855 PotentialImplicitProtocols.push_back(ProtDecl);
857 if (PotentialImplicitProtocols.empty())
864 for (
unsigned i = 0, e = PotentialImplicitProtocols.size(); i != e; i++)
866 PotentialImplicitProtocols[i]))
867 ConformingProtocols.push_back(PotentialImplicitProtocols[i]);
869 if (ConformingProtocols.empty())
875 for (
unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
878 for (
unsigned i1 = 0, e1 = ConformingProtocols.size(); i1 != e1; i1++) {
880 if (PDecl == TargetPDecl)
889 MinimalConformingProtocols.push_back(TargetPDecl);
891 if (MinimalConformingProtocols.empty())
896 Editor->commit(commit);
899 void ObjCMigrateASTConsumer::CacheObjCNSIntegerTypedefed(
903 if (NSAPIObj->isObjCNSIntegerType(qt))
904 NSIntegerTypedefed = TypedefDcl;
905 else if (NSAPIObj->isObjCNSUIntegerType(qt))
906 NSUIntegerTypedefed = TypedefDcl;
909 bool ObjCMigrateASTConsumer::migrateNSEnumDecl(
ASTContext &Ctx,
916 if (NSIntegerTypedefed) {
917 TypedefDcl = NSIntegerTypedefed;
918 NSIntegerTypedefed =
nullptr;
920 else if (NSUIntegerTypedefed) {
921 TypedefDcl = NSUIntegerTypedefed;
922 NSUIntegerTypedefed =
nullptr;
926 FileID FileIdOfTypedefDcl =
930 if (FileIdOfTypedefDcl != FileIdOfEnumDcl)
937 StringRef NSIntegerName = NSAPIObj->GetNSIntegralKind(qt);
939 if (NSIntegerName.empty()) {
942 if (EnumTy->getDecl() == EnumDcl) {
944 if (!InsertFoundation(Ctx, TypedefDcl->
getBeginLoc()))
948 Editor->commit(commit);
957 if (!InsertFoundation(Ctx, TypedefDcl->
getBeginLoc()))
961 commit, NSIntegerName, NSOptions);
962 Editor->commit(commit);
967 const ObjCMigrateASTConsumer &ASTC,
973 std::string ClassString;
975 TypeLoc TL = TSInfo->getTypeLoc();
977 ClassString =
"instancetype";
982 ClassString +=
" (instancetype)";
985 commit.
replace(R, ClassString);
986 ASTC.Editor->commit(commit);
993 std::string ClassString;
995 TypeLoc TL = TSInfo->getTypeLoc();
997 ClassString = IDecl->
getName();
1003 ClassString =
"+ (";
1004 ClassString += IDecl->
getName(); ClassString +=
"*)";
1007 commit.
replace(R, ClassString);
1008 ASTC.Editor->commit(commit);
1011 void ObjCMigrateASTConsumer::migrateMethodInstanceType(
ASTContext &Ctx,
1017 std::string ClassName;
1018 switch (OIT_Family) {
1020 migrateFactoryMethod(Ctx, CDecl, OM);
1023 ClassName =
"NSArray";
1026 ClassName =
"NSDictionary";
1045 IDecl = CatDecl->getClassInterface();
1046 else if (
ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(CDecl))
1051 migrateFactoryMethod(Ctx, CDecl, OM);
1068 T = TD->getDecl()->getUnderlyingType();
1073 if (UPointeeT->isRecordType()) {
1092 const AvailabilityAttr *AA1 = dyn_cast<AvailabilityAttr>(At1);
1095 const AvailabilityAttr *AA2 = dyn_cast<AvailabilityAttr>(At2);
1097 VersionTuple Introduced1 = AA1->getIntroduced();
1098 VersionTuple Deprecated1 = AA1->getDeprecated();
1099 VersionTuple Obsoleted1 = AA1->getObsoleted();
1100 bool IsUnavailable1 = AA1->getUnavailable();
1101 VersionTuple Introduced2 = AA2->getIntroduced();
1102 VersionTuple Deprecated2 = AA2->getDeprecated();
1103 VersionTuple Obsoleted2 = AA2->getObsoleted();
1104 bool IsUnavailable2 = AA2->getUnavailable();
1108 IsUnavailable1 == IsUnavailable2);
1112 bool &AvailabilityArgsMatch) {
1114 for (
unsigned i = 0, e = Attrs1.size(); i != e; i++) {
1116 for (
unsigned j = 0, f = Attrs2.size(); j != f; j++) {
1120 if (Attrs1[i]->
getKind() == Attrs2[j]->getKind()) {
1121 if (AvailabilityArgsMatch)
1141 bool &AvailabilityArgsMatch) {
1146 AvailabilityArgsMatch =
true;
1150 if (match && (Attrs2.size() > Attrs1.size()))
1159 std::string NameString = Name;
1165 bool ObjCMigrateASTConsumer::migrateProperty(
ASTContext &Ctx,
1189 unsigned LengthOfPrefix = 0;
1190 if (!SetterMethod) {
1192 StringRef getterNameString = getterName->
getName();
1193 bool IsPrefix = getterNameString.startswith(
"is");
1198 if (IsPrefix || getterNameString.startswith(
"get")) {
1199 LengthOfPrefix = (IsPrefix ? 2 : 3);
1200 const char *CGetterName = getterNameString.data() + LengthOfPrefix;
1205 if (CGetterName[0] &&
isUppercase(CGetterName[0])) {
1206 getterName = &Ctx.
Idents.
get(CGetterName);
1219 bool AvailabilityArgsMatch;
1220 if (SetterMethod->isDeprecated() ||
1225 QualType SRT = SetterMethod->getReturnType();
1228 const ParmVarDecl *argDecl = *SetterMethod->param_begin();
1235 (ASTMigrateActions &
1237 (ASTMigrateActions &
1239 AvailabilityArgsMatch);
1240 Editor->commit(commit);
1249 (ASTMigrateActions &
1251 (ASTMigrateActions &
1254 Editor->commit(commit);
1260 void ObjCMigrateASTConsumer::migrateNsReturnsInnerPointer(
ASTContext &Ctx,
1264 OM->
hasAttr<ObjCReturnsInnerPointerAttr>())
1269 !NSAPIObj->isMacroDefined(
"NS_RETURNS_INNER_POINTER"))
1274 Editor->commit(commit);
1277 void ObjCMigrateASTConsumer::migratePropertyNsReturnsInnerPointer(
ASTContext &Ctx,
1282 !NSAPIObj->isMacroDefined(
"NS_RETURNS_INNER_POINTER"))
1286 Editor->commit(commit);
1289 void ObjCMigrateASTConsumer::migrateAllMethodInstaceType(
ASTContext &Ctx,
1295 for (
auto *Method : CDecl->
methods()) {
1298 migrateMethodInstanceType(Ctx, CDecl, Method);
1302 void ObjCMigrateASTConsumer::migrateFactoryMethod(
ASTContext &Ctx,
1316 IDecl = CatDecl->getClassInterface();
1317 else if (
ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(CDecl))
1323 std::string StringClassName = IDecl->
getName();
1324 StringRef LoweredClassName(StringClassName);
1325 std::string StringLoweredClassName = LoweredClassName.lower();
1326 LoweredClassName = StringLoweredClassName;
1333 std::string MethodName = MethodIdName->
getName();
1335 StringRef STRefMethodName(MethodName);
1337 if (STRefMethodName.startswith(
"standard"))
1338 len = strlen(
"standard");
1339 else if (STRefMethodName.startswith(
"shared"))
1340 len = strlen(
"shared");
1341 else if (STRefMethodName.startswith(
"default"))
1342 len = strlen(
"default");
1345 MethodName = STRefMethodName.substr(len);
1347 std::string MethodNameSubStr = MethodName.substr(0, 3);
1348 StringRef MethodNamePrefix(MethodNameSubStr);
1349 std::string StringLoweredMethodNamePrefix = MethodNamePrefix.lower();
1350 MethodNamePrefix = StringLoweredMethodNamePrefix;
1351 size_t Ix = LoweredClassName.rfind(MethodNamePrefix);
1352 if (Ix == StringRef::npos)
1354 std::string ClassNamePostfix = LoweredClassName.substr(Ix);
1355 StringRef LoweredMethodName(MethodName);
1356 std::string StringLoweredMethodName = LoweredMethodName.lower();
1357 LoweredMethodName = StringLoweredMethodName;
1358 if (!LoweredMethodName.startswith(ClassNamePostfix))
1371 Ty = TD->getDecl()->getUnderlyingType();
1397 void ObjCMigrateASTConsumer::AnnotateImplicitBridging(
ASTContext &Ctx) {
1398 if (CFFunctionIBCandidates.empty())
1400 if (!NSAPIObj->isMacroDefined(
"CF_IMPLICIT_BRIDGING_ENABLED")) {
1401 CFFunctionIBCandidates.clear();
1406 const Decl *FirstFD = CFFunctionIBCandidates[0];
1407 const Decl *LastFD =
1408 CFFunctionIBCandidates[CFFunctionIBCandidates.size()-1];
1409 const char *PragmaString =
"\nCF_IMPLICIT_BRIDGING_ENABLED\n\n";
1412 PragmaString =
"\n\nCF_IMPLICIT_BRIDGING_DISABLED\n";
1416 if (isa<FunctionDecl>(LastFD)) {
1426 Editor->commit(commit);
1428 CFFunctionIBCandidates.clear();
1431 void ObjCMigrateASTConsumer::migrateCFAnnotation(
ASTContext &Ctx,
const Decl *
Decl) {
1435 if (Decl->
hasAttr<CFAuditedTransferAttr>()) {
1436 assert(CFFunctionIBCandidates.empty() &&
1437 "Cannot have audited functions/methods inside user " 1438 "provided CF_IMPLICIT_BRIDGING_ENABLE");
1443 if (
const FunctionDecl *FuncDecl = dyn_cast<FunctionDecl>(Decl)) {
1444 CF_BRIDGING_KIND AuditKind = migrateAddFunctionAnnotation(Ctx, FuncDecl);
1445 if (AuditKind == CF_BRIDGING_ENABLE) {
1446 CFFunctionIBCandidates.push_back(Decl);
1450 else if (AuditKind == CF_BRIDGING_MAY_INCLUDE) {
1451 if (!CFFunctionIBCandidates.empty()) {
1452 CFFunctionIBCandidates.push_back(Decl);
1458 AnnotateImplicitBridging(Ctx);
1461 migrateAddMethodAnnotation(Ctx, cast<ObjCMethodDecl>(Decl));
1462 AnnotateImplicitBridging(Ctx);
1466 void ObjCMigrateASTConsumer::AddCFAnnotations(
ASTContext &Ctx,
1467 const RetainSummary *RS,
1469 bool ResultAnnotated) {
1471 if (!ResultAnnotated) {
1473 const char *AnnotationString =
nullptr;
1475 if (Ret.
isOwned() && NSAPIObj->isMacroDefined(
"CF_RETURNS_RETAINED"))
1476 AnnotationString =
" CF_RETURNS_RETAINED";
1478 NSAPIObj->isMacroDefined(
"CF_RETURNS_NOT_RETAINED"))
1479 AnnotationString =
" CF_RETURNS_NOT_RETAINED";
1482 if (Ret.
isOwned() && NSAPIObj->isMacroDefined(
"NS_RETURNS_RETAINED"))
1483 AnnotationString =
" NS_RETURNS_RETAINED";
1486 if (AnnotationString) {
1489 Editor->commit(commit);
1494 pe = FuncDecl->
param_end(); pi != pe; ++pi, ++i) {
1498 !pd->
hasAttr<CFConsumedAttr>() &&
1499 NSAPIObj->isMacroDefined(
"CF_CONSUMED")) {
1502 Editor->commit(commit);
1504 !pd->
hasAttr<NSConsumedAttr>() &&
1505 NSAPIObj->isMacroDefined(
"NS_CONSUMED")) {
1508 Editor->commit(commit);
1513 ObjCMigrateASTConsumer::CF_BRIDGING_KIND
1514 ObjCMigrateASTConsumer::migrateAddFunctionAnnotation(
1518 return CF_BRIDGING_NONE;
1520 const RetainSummary *RS =
1521 getSummaryManager(Ctx).getSummary(AnyCall(FuncDecl));
1522 bool FuncIsReturnAnnotated = (FuncDecl->
hasAttr<CFReturnsRetainedAttr>() ||
1523 FuncDecl->
hasAttr<CFReturnsNotRetainedAttr>() ||
1524 FuncDecl->
hasAttr<NSReturnsRetainedAttr>() ||
1525 FuncDecl->
hasAttr<NSReturnsNotRetainedAttr>() ||
1526 FuncDecl->
hasAttr<NSReturnsAutoreleasedAttr>());
1529 if (FuncIsReturnAnnotated && FuncDecl->
getNumParams() == 0)
1530 return CF_BRIDGING_NONE;
1532 bool ReturnCFAudited =
false;
1533 if (!FuncIsReturnAnnotated) {
1537 ReturnCFAudited =
true;
1539 return CF_BRIDGING_NONE;
1544 bool ArgCFAudited =
false;
1546 pe = FuncDecl->
param_end(); pi != pe; ++pi, ++i) {
1552 ArgCFAudited =
true;
1554 ArgCFAudited =
true;
1558 AddCFAnnotations(Ctx, RS, FuncDecl, FuncIsReturnAnnotated);
1559 return CF_BRIDGING_NONE;
1563 if (ReturnCFAudited || ArgCFAudited)
1564 return CF_BRIDGING_ENABLE;
1566 return CF_BRIDGING_MAY_INCLUDE;
1569 void ObjCMigrateASTConsumer::migrateARCSafeAnnotation(
ASTContext &Ctx,
1571 if (!isa<ObjCInterfaceDecl>(CDecl) || CDecl->
isDeprecated())
1575 for (
const auto *Method : CDecl->
methods())
1576 migrateCFAnnotation(Ctx, Method);
1579 void ObjCMigrateASTConsumer::AddCFAnnotations(
ASTContext &Ctx,
1580 const RetainSummary *RS,
1582 bool ResultAnnotated) {
1584 if (!ResultAnnotated) {
1586 const char *AnnotationString =
nullptr;
1588 if (Ret.
isOwned() && NSAPIObj->isMacroDefined(
"CF_RETURNS_RETAINED"))
1589 AnnotationString =
" CF_RETURNS_RETAINED";
1591 NSAPIObj->isMacroDefined(
"CF_RETURNS_NOT_RETAINED"))
1592 AnnotationString =
" CF_RETURNS_NOT_RETAINED";
1605 if (Ret.
isOwned() && NSAPIObj->isMacroDefined(
"NS_RETURNS_RETAINED"))
1606 AnnotationString =
" NS_RETURNS_RETAINED";
1611 if (AnnotationString) {
1614 Editor->commit(commit);
1619 pe = MethodDecl->
param_end(); pi != pe; ++pi, ++i) {
1624 && !pd->
hasAttr<CFConsumedAttr>() &&
1625 NSAPIObj->isMacroDefined(
"CF_CONSUMED")) {
1628 Editor->commit(commit);
1633 void ObjCMigrateASTConsumer::migrateAddMethodAnnotation(
1639 const RetainSummary *RS =
1640 getSummaryManager(Ctx).getSummary(AnyCall(MethodDecl));
1642 bool MethodIsReturnAnnotated =
1643 (MethodDecl->
hasAttr<CFReturnsRetainedAttr>() ||
1644 MethodDecl->
hasAttr<CFReturnsNotRetainedAttr>() ||
1645 MethodDecl->
hasAttr<NSReturnsRetainedAttr>() ||
1646 MethodDecl->
hasAttr<NSReturnsNotRetainedAttr>() ||
1647 MethodDecl->
hasAttr<NSReturnsAutoreleasedAttr>());
1649 if (RS->getReceiverEffect().getKind() ==
DecRef &&
1650 !MethodDecl->
hasAttr<NSConsumesSelfAttr>() &&
1653 NSAPIObj->isMacroDefined(
"NS_CONSUMES_SELF")) {
1656 Editor->commit(commit);
1660 if (MethodIsReturnAnnotated &&
1664 if (!MethodIsReturnAnnotated) {
1669 AddCFAnnotations(Ctx, RS, MethodDecl,
false);
1678 pe = MethodDecl->
param_end(); pi != pe; ++pi, ++i) {
1683 AddCFAnnotations(Ctx, RS, MethodDecl, MethodIsReturnAnnotated);
1692 bool shouldVisitTemplateInstantiations()
const {
return false; }
1693 bool shouldWalkTypesOfTypeLocs()
const {
return false; }
1706 return !SuperInitChecker().TraverseStmt(MD->
getBody());
1709 void ObjCMigrateASTConsumer::inferDesignatedInitializers(
1716 if (!NSAPIObj->isMacroDefined(
"NS_DESIGNATED_INITIALIZER"))
1720 if (MD->isDeprecated() ||
1721 MD->getMethodFamily() !=
OMF_init ||
1722 MD->isDesignatedInitializerForTheInterface())
1731 Editor->commit(commit);
1736 bool ObjCMigrateASTConsumer::InsertFoundation(
ASTContext &Ctx,
1738 if (FoundationIncluded)
1742 auto *nsEnumId = &Ctx.
Idents.
get(
"NS_ENUM");
1744 FoundationIncluded =
true;
1749 commit.
insert(Loc,
"#ifndef NS_ENUM\n@import Foundation;\n#endif\n");
1751 commit.
insert(Loc,
"#ifndef NS_ENUM\n#import <Foundation/Foundation.h>\n#endif\n");
1752 Editor->commit(commit);
1753 FoundationIncluded =
true;
1763 RewritesReceiver(
Rewriter &Rewrite) : Rewrite(Rewrite) { }
1775 llvm::raw_ostream &
OS;
1779 : SourceMgr(SM), OS(OS) {
1782 ~JSONEditWriter()
override { OS <<
"]\n"; }
1785 struct EntryWriter {
1787 llvm::raw_ostream &OS;
1790 : SourceMgr(SM), OS(OS) {
1804 llvm::sys::fs::make_absolute(Path);
1805 OS <<
" \"file\": \"";
1806 OS.write_escaped(Path.str()) <<
"\",\n";
1807 OS <<
" \"offset\": " << Offset <<
",\n";
1812 std::pair<FileID, unsigned>
Begin =
1814 std::pair<FileID, unsigned>
End =
1816 assert(Begin.first == End.first);
1817 assert(Begin.second <= End.second);
1818 unsigned Length = End.second - Begin.second;
1820 OS <<
" \"remove\": " << Length <<
",\n";
1823 void writeText(StringRef
Text) {
1824 OS <<
" \"text\": \"";
1825 OS.write_escaped(Text) <<
"\",\n";
1830 EntryWriter Writer(SourceMgr, OS);
1831 Writer.writeLoc(Loc);
1832 Writer.writeText(Text);
1836 EntryWriter Writer(SourceMgr, OS);
1838 Writer.writeRemove(Range);
1839 Writer.writeText(Text);
1843 EntryWriter Writer(SourceMgr, OS);
1845 Writer.writeRemove(Range);
1851 void ObjCMigrateASTConsumer::HandleTranslationUnit(
ASTContext &Ctx) {
1859 if (FileId.
isValid() && FileId != FID) {
1861 AnnotateImplicitBridging(Ctx);
1865 if (canModify(CDecl))
1866 migrateObjCContainerDecl(Ctx, CDecl);
1868 if (canModify(CatDecl))
1869 migrateObjCContainerDecl(Ctx, CatDecl);
1872 ObjCProtocolDecls.insert(PDecl->getCanonicalDecl());
1873 if (canModify(PDecl))
1874 migrateObjCContainerDecl(Ctx, PDecl);
1877 dyn_cast<ObjCImplementationDecl>(*D)) {
1880 migrateProtocolConformance(Ctx, ImpDecl);
1882 else if (
const EnumDecl *ED = dyn_cast<EnumDecl>(*D)) {
1890 if (migrateNSEnumDecl(Ctx, ED, TD) && TD)
1894 migrateNSEnumDecl(Ctx, ED,
nullptr);
1896 else if (
const TypedefDecl *TD = dyn_cast<TypedefDecl>(*D)) {
1904 if (
const EnumDecl *ED = dyn_cast<EnumDecl>(*N)) {
1905 if (canModify(ED)) {
1907 if (
const TypedefDecl *TDF = dyn_cast<TypedefDecl>(*N)) {
1909 if (migrateNSEnumDecl(Ctx, ED, TDF)) {
1911 CacheObjCNSIntegerTypedefed(TD);
1915 if (migrateNSEnumDecl(Ctx, ED, TD)) {
1921 CacheObjCNSIntegerTypedefed(TD);
1923 else if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(*D)) {
1926 migrateCFAnnotation(Ctx, FD);
1930 bool CanModify = canModify(CDecl);
1934 migrateAllMethodInstaceType(Ctx, CDecl);
1938 migrateARCSafeAnnotation(Ctx, CDecl);
1942 ImplD = dyn_cast<ObjCImplementationDecl>(*D)) {
1945 inferDesignatedInitializers(Ctx, ImplD);
1949 AnnotateImplicitBridging(Ctx);
1954 llvm::raw_fd_ostream
OS(MigrateDir, EC, llvm::sys::fs::F_None);
1963 Editor->applyRewrites(Writer);
1968 RewritesReceiver Rec(rewriter);
1969 Editor->applyRewrites(Rec);
1972 I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) {
1978 llvm::raw_svector_ostream vecOS(newText);
1980 std::unique_ptr<llvm::MemoryBuffer> memBuf(
1981 llvm::MemoryBuffer::getMemBufferCopy(
1982 StringRef(newText.data(), newText.size()), file->
getName()));
1985 Remapper.
remap(filePath.str(), std::move(memBuf));
2001 using namespace llvm::sys::fs;
2002 using namespace llvm::sys::path;
2004 std::vector<std::string> Filenames;
2005 if (DirPath.empty() || !is_directory(DirPath))
2009 directory_iterator DI = directory_iterator(DirPath, EC);
2010 directory_iterator DE;
2011 for (; !EC && DI != DE; DI = DI.increment(EC)) {
2012 if (is_regular_file(DI->path()))
2013 Filenames.push_back(filename(DI->path()));
2019 std::unique_ptr<ASTConsumer>
2024 unsigned ObjCMTOpts = ObjCMTAction;
2035 std::vector<std::string> WhiteList =
2037 return llvm::make_unique<ObjCMigrateASTConsumer>(
2050 EditEntry() : File(),
Offset(), RemoveLen() {}
2058 Entry.Offset = unsigned(-1);
2063 Entry.Offset = unsigned(-2);
2067 llvm::FoldingSetNodeID
ID;
2068 ID.AddPointer(Val.File);
2069 ID.AddInteger(Val.Offset);
2070 ID.AddInteger(Val.RemoveLen);
2071 ID.AddString(Val.Text);
2072 return ID.ComputeHash();
2074 static bool isEqual(
const EditEntry &LHS,
const EditEntry &RHS) {
2075 return LHS.File == RHS.File &&
2076 LHS.Offset == RHS.Offset &&
2077 LHS.RemoveLen == RHS.RemoveLen &&
2078 LHS.Text == RHS.Text;
2084 class RemapFileParser {
2088 RemapFileParser(
FileManager &FileMgr) : FileMgr(FileMgr) { }
2093 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
2094 llvm::MemoryBuffer::getFile(File);
2099 Stream YAMLStream(FileBufOrErr.get()->getMemBufferRef(),
SM);
2100 document_iterator I = YAMLStream.begin();
2101 if (I == YAMLStream.end())
2103 Node *Root = I->getRoot();
2107 SequenceNode *SeqNode = dyn_cast<SequenceNode>(Root);
2111 for (SequenceNode::iterator
2112 AI = SeqNode->begin(), AE = SeqNode->end(); AI != AE; ++AI) {
2113 MappingNode *MapNode = dyn_cast<MappingNode>(&*AI);
2116 parseEdit(MapNode, Entries);
2123 void parseEdit(llvm::yaml::MappingNode *
Node,
2127 bool Ignore =
false;
2129 for (MappingNode::iterator
2130 KVI = Node->begin(), KVE = Node->end(); KVI != KVE; ++KVI) {
2131 ScalarNode *KeyString = dyn_cast<ScalarNode>((*KVI).getKey());
2135 StringRef Key = KeyString->getValue(KeyStorage);
2137 ScalarNode *ValueString = dyn_cast<ScalarNode>((*KVI).getValue());
2141 StringRef Val = ValueString->getValue(ValueStorage);
2143 if (Key ==
"file") {
2148 }
else if (Key ==
"offset") {
2149 if (Val.getAsInteger(10, Entry.Offset))
2151 }
else if (Key ==
"remove") {
2152 if (Val.getAsInteger(10, Entry.RemoveLen))
2154 }
else if (Key ==
"text") {
2160 Entries.push_back(Entry);
2182 I = Edits.begin(), E = Edits.end(); I != E; ++I) {
2183 const EditEntry &Entry = *I;
2184 assert(Entry.File == FE);
2188 if (Entry.RemoveLen != 0) {
2195 commit.insert(Loc, Entry.Text);
2196 }
else if (Entry.Text.empty()) {
2197 commit.remove(Range);
2199 commit.replace(Range, Entry.Text);
2205 RewritesReceiver Rec(rewriter);
2210 llvm::raw_svector_ostream
OS(NewText);
2215 if (fs::createTemporaryFile(path::filename(FE->
getName()),
2216 path::extension(FE->
getName()).drop_front(), FD,
2219 return std::string();
2222 llvm::raw_fd_ostream TmpOut(FD,
true);
2223 TmpOut.write(NewText.data(), NewText.size());
2226 return TempPath.str();
2230 std::vector<std::pair<std::string,std::string> > &remap,
2233 bool hasErrorOccurred =
false;
2237 RemapFileParser
Parser(FileMgr);
2242 DiagClient,
false));
2244 typedef llvm::DenseMap<const FileEntry *, std::vector<EditEntry> >
2246 FileEditEntriesTy FileEditEntries;
2251 I = remapFiles.begin(), E = remapFiles.end(); I != E; ++I) {
2253 if (Parser.parse(*I, Entries))
2257 EI = Entries.begin(), EE = Entries.end(); EI != EE; ++EI) {
2258 EditEntry &Entry = *EI;
2261 std::pair<llvm::DenseSet<EditEntry>::iterator,
bool>
2262 Insert = EntriesSet.insert(Entry);
2266 FileEditEntries[Entry.File].push_back(Entry);
2270 for (FileEditEntriesTy::iterator
2271 I = FileEditEntries.begin(), E = FileEditEntries.end(); I != E; ++I) {
2274 if (TempFile.empty()) {
2275 hasErrorOccurred =
true;
2279 remap.emplace_back(I->first->getName(), TempFile);
2282 return hasErrorOccurred;
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.
bool BeginInvocation(CompilerInstance &CI) override
Callback before starting processing a single input, giving the opportunity to modify the CompilerInvo...
Defines the clang::ASTContext interface.
bool remove(CharSourceRange range)
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override
Create the AST consumer object for this action, if supported.
static bool AttributesMatch(const Decl *Decl1, const Decl *Decl2, bool &AvailabilityArgsMatch)
AttributesMatch - This routine checks list of attributes for two decls.
Represents a function declaration or definition.
static bool MatchTwoAttributeLists(const AttrVec &Attrs1, const AttrVec &Attrs2, bool &AvailabilityArgsMatch)
Enable migration to modern ObjC readwrite property.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
The receiver is an object instance.
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()
PointerType - C99 6.7.5.1 - Pointer Declarators.
QualType getPointeeType() const
A (possibly-)qualified type.
bool isBlockPointerType() const
unsigned param_size() const
bool rewriteToObjCSubscriptSyntax(const ObjCMessageExpr *Msg, const NSAPI &NS, Commit &commit)
Implements support for file system lookup, file system caching, and directory search management...
ObjCInterfaceDecl * getClassInterface()
ASTConsumer - This is an abstract interface that should be implemented by clients that read ASTs...
Enable migration to modern ObjC readonly property.
Defines the clang::FileManager interface and associated types.
bool rewriteToObjCLiteralSyntax(const ObjCMessageExpr *Msg, const NSAPI &NS, Commit &commit, const ParentMap *PMap)
static bool hasSuperInitCall(const ObjCMethodDecl *MD)
SourceRange getBraceRange() const
DominatorTree GraphTraits specialization so the DominatorTree can be iterable by generic graph iterat...
Stmt - This represents one statement.
bool insertWrap(StringRef before, CharSourceRange range, StringRef after)
SourceLocation getSuperClassLoc() const
Retrieve the starting location of the superclass.
Represents the declaration of a typedef-name via the 'typedef' type specifier.
use NS_NONATOMIC_IOSONLY for property 'atomic' attribute
ObjKind getObjKind() const
QualType getQualifiedType(SplitQualType split) const
Un-split a SplitQualType.
Decl - This represents one declaration (or definition), e.g.
SourceLocation getBeginLoc() const LLVM_READONLY
The argument has its reference count increased by 1.
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)
ObjCProtocolDecl * lookupNestedProtocol(IdentifierInfo *Name)
DiagnosticsEngine & getDiagnostics() const
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
bool insertAfterToken(SourceLocation loc, StringRef text, bool beforePreviousInsertions=false)
A Range represents the closed range [from, to].
SourceLocation getEndLoc() const LLVM_READONLY
A container of type source information.
Parser - This implements a parser for the C family of languages.
bool insertFromRange(SourceLocation loc, CharSourceRange range, bool afterToken=false, bool beforePreviousInsertions=false)
ArrayRef< ParmVarDecl * >::const_iterator param_const_iterator
param_const_iterator param_end() const
SourceLocation getEndLoc() const
Get the end source location.
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
enumerator_range enumerators() const
void removeObjCLifetime()
QualType getReturnType() const
SourceLocation findSemiAfterLocation(SourceLocation loc, ASTContext &Ctx, bool IsDecl=false)
'Loc' is the end of a statement range.
static std::vector< std::string > getWhiteListFilenames(StringRef DirPath)
const T * getAs() const
Member-template getAs<specific type>'.
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...
ObjCMethodDecl - Represents an instance or class method declaration.
ObjKind getObjKind() const
RewriteBuffer - As code is rewritten, SourceBuffer's from the original input with modifications get a...
Describes how types, statements, expressions, and declarations should be printed. ...
Represents a parameter to a function.
bool isLiteral() const
Return true if this is a "literal", like a numeric constant, string, etc.
The collection of all-type qualifiers we support.
static EditEntry getTombstoneKey()
SourceLocation getDeclaratorEndLoc() const
Returns the location where the declarator ends.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Base wrapper for a particular "section" of type source info.
bool insert(SourceLocation loc, StringRef text, bool afterToken=false, bool beforePreviousInsertions=false)
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.
instprop_range instance_properties() const
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)
Enable migration to modern ObjC literals.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
The results of name lookup within a DeclContext.
const ParmVarDecl *const * param_const_iterator
ObjCMethodFamily
A family of Objective-C methods.
FullExpr - Represents a "full-expression" node.
SourceLocation getBeginLoc() const LLVM_READONLY
bool isObjCIdType() const
instmeth_range instance_methods() const
method_range methods() const
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.
bool ReplaceText(SourceLocation Start, unsigned OrigLength, StringRef NewStr)
ReplaceText - This method replaces a range of characters in the input buffer with a new string...
SourceLocation findLocationAfterSemi(SourceLocation loc, ASTContext &Ctx, bool IsDecl=false)
'Loc' is the end of a statement range.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
unsigned SuppressStrongLifetime
When true, suppress printing of the __strong lifetime qualifier in ARC.
static void ReplaceWithInstancetype(ASTContext &Ctx, const ObjCMigrateASTConsumer &ASTC, ObjCMethodDecl *OM)
bool isDeprecated(std::string *Message=nullptr) const
Determine whether this declaration is marked 'deprecated'.
ObjCMethodFamily getMethodFamily() const
Determines the family of this method.
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)
static const char * PropertyMemoryAttribute(ASTContext &Context, QualType ArgType)
ObjCContainerDecl - Represents a container for method declarations.
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()
static bool UseNSOptionsMacro(Preprocessor &PP, ASTContext &Ctx, const EnumDecl *EnumDcl)
static bool rewriteToNSEnumDecl(const EnumDecl *EnumDcl, const TypedefDecl *TypedefDcl, const NSAPI &NS, edit::Commit &commit, StringRef NSIntegerName, bool NSOptions)
SourceLocation getBeginLoc() const LLVM_READONLY
Concrete class used by the front-end to report problems and issues.
bool BeginInvocation(CompilerInstance &CI) override
Callback before starting processing a single input, giving the opportunity to modify the CompilerInvo...
const clang::PrintingPolicy & getPrintingPolicy() const
A builtin binary operation expression such as "x + y" or "x <= y".
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
ObjCProtocolDecl * getDefinition()
Retrieve the definition of this protocol, if any.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
static bool reportDiag(const Twine &Err, DiagnosticsEngine &Diag)
Represents an Objective-C protocol declaration.
LLVM_READONLY bool isUppercase(unsigned char c)
Return true if this character is an uppercase ASCII letter: [A-Z].
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.
QualType getReturnType() const
Enable migration of ObjC methods to 'instancetype'.
static EditEntry getEmptyKey()
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point...
param_iterator param_begin()
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
const FileEntry * getFile(StringRef Filename, bool OpenFile=false, bool CacheFailure=true)
Lookup, cache, and verify the specified file (real or virtual).
ObjCProtocolDecl * lookupProtocolNamed(IdentifierInfo *PName)
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...
SourceLocation getEndLoc() const LLVM_READONLY
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
bool ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl, const ObjCMethodDecl *MethodImp)
Enable migration to add conforming protocols.
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_].
SourceLocation getBeginLoc() const
Get the begin source location.
This represents one expression.
Represents a character-granular source range.
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
FileID createFileID(const FileEntry *SourceFile, SourceLocation IncludePos, SrcMgr::CharacteristicKind FileCharacter, int LoadedID=0, unsigned LoadedOffset=0)
Create a new FileID that represents the specified file being #included from the specified IncludePosi...
bool isObjCBuiltinType() const
ASTContext & getASTContext() const
bool isObjCRetainableType() const
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
SourceLocation getSelectorStartLoc() const
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file. ...
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)
ObjCInterfaceDecl * getSuperClass() const
Expr ** getArgs()
Retrieve the arguments to this message, not including the receiver.
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't...
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
protocol_loc_iterator protocol_loc_end() const
Enable annotation of ObjCMethods of all kinds.
static bool IsValidIdentifier(ASTContext &Ctx, const char *Name)
bool isCFObjectRef(QualType T)
An expression that sends a message to the given Objective-C object or class.
static bool subscriptOperatorNeedsParens(const Expr *FullExpr)
SourceLocation getEnd() const
bool isInstanceMethod() const
ReceiverKind getReceiverKind() const
Determine the kind of receiver that this message is being sent to.
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...
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
bool isNull() const
Return true if this QualType doesn't point to a type yet.
SourceLocation getEndLoc() const LLVM_READONLY
static CharSourceRange getCharRange(SourceRange R)
SourceManager & getSourceManager() const
TypeSourceInfo * getReturnTypeSourceInfo() const
RecordDecl * getDecl() const
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override
Create the AST consumer object for this action, if supported.
static void ReplaceWithClasstype(const ObjCMigrateASTConsumer &ASTC, ObjCMethodDecl *OM)
There is no lifetime qualification on this type.
unsigned getNumArgs() const
Return the number of actual arguments in this message, not counting the receiver. ...
LLVM_READONLY char toLowercase(char c)
Converts the given ASCII character to its lowercase equivalent.
Assigning into this object requires the old value to be released and the new value to be retained...
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)
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.
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of enums...
StringRef getName() const
static bool rewriteToObjCInterfaceDecl(const ObjCInterfaceDecl *IDecl, llvm::SmallVectorImpl< ObjCProtocolDecl *> &ConformingProtocols, const NSAPI &NS, edit::Commit &commit)
decl_iterator decls_begin() const
static unsigned getHashValue(const EditEntry &Val)
prefer 'atomic' property over 'nonatomic'.
bool flushToDisk(StringRef outputDir, DiagnosticsEngine &Diag)
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
Options for controlling the compiler diagnostics engine.
static void MigrateBlockOrFunctionPointerTypeVariable(std::string &PropertyString, const std::string &TypeString, const char *name)
ObjCMethodFamily getMethodFamily() const
Records preprocessor conditional directive regions and allows querying in which region source locatio...
IdentifierTable & getIdentifierTable()
static bool ClassImplementsAllMethodsAndProperties(ASTContext &Ctx, const ObjCImplementationDecl *ImpDecl, const ObjCInterfaceDecl *IDecl, ObjCProtocolDecl *Protocol)
Cached information about one file (either on disk or in the virtual file system). ...
const RewriteBuffer * getRewriteBufferFor(FileID FID) const
getRewriteBufferFor - Return the rewrite buffer for the specified FileID.
Stmt * getBody() const override
Retrieve the body of this method, if it has one.
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...
SourceLocation getSuperLoc() const
Retrieve the location of the 'super' keyword for a class or instance message to 'super', otherwise an invalid source location.
ObjCInterfaceDecl * lookupInheritedClass(const IdentifierInfo *ICName)
lookupInheritedClass - This method returns ObjCInterfaceDecl * of the super class whose name is passe...
ObjCCategoryDecl - Represents a category declaration.
Enable inferring NS_DESIGNATED_INITIALIZER for ObjC methods.
static bool AvailabilityAttrsMatch(Attr *At1, Attr *At2)
AvailabilityAttrsMatch - This routine checks that if comparing two availability attributes, all their components match.
annotate property with NS_RETURNS_INNER_POINTER
SourceLocation getSelectorLoc(unsigned Index) const
bool isObjCObjectPointerType() const
bool isAnyPointerType() const
MacroDefinition getMacroDefinitionAtLoc(const IdentifierInfo *II, SourceLocation Loc)
Enable converting setter/getter expressions to property-dot syntx.
Represents one property declaration in an Objective-C interface.
bool isImplicit() const
Indicates whether the message send was implicitly generated by the implementation.
unsigned getCustomDiagID(Level L, const char(&FormatString)[N])
Return an ID for a diagnostic with the specified format string and level.
const ObjCMethodDecl * getMethodDecl() const
static StringRef GetUnsignedName(StringRef NSIntegerName)
std::map< FileID, RewriteBuffer >::iterator buffer_iterator
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
QualType getObjCInstanceType()
Retrieve the Objective-C "instancetype" type, if already known; otherwise, returns a NULL type;...
StringRef getName() const
Return the actual identifier string.
void setIgnoreAllWarnings(bool Val)
When set to true, any unmapped warnings are ignored.
decl_iterator - Iterates through the declarations stored within this context.
Expr * getInstanceReceiver()
Returns the object expression (receiver) for an instance message, or null for a message that is not a...
ast_type_traits::DynTypedNode Node
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
const ObjCInterfaceDecl * getClassInterface() const
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)
bool isMacroDefined(StringRef Id) const
Returns true if Id is currently defined as a macro.
static void rewriteToNSMacroDecl(ASTContext &Ctx, const EnumDecl *EnumDcl, const TypedefDecl *TypedefDcl, const NSAPI &NS, edit::Commit &commit, bool IsNSIntegerType)
const ObjCProtocolList & getReferencedProtocols() const
Used for handling and querying diagnostic IDs.
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
SourceManager & getSourceManager() const
Return the current source manager.
bool hasObjCLifetime() const
Enable migration to modern ObjC subscripting.
unsigned getLength() const
param_iterator param_end()
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 'objc_designate...
Represents a pointer to an Objective C object.
static bool IsVoidStarType(QualType Ty)
const char * getLiteralData() const
getLiteralData - For a literal token (numeric constant, string, etc), this returns a pointer to the s...
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
ObjCImplementationDecl - Represents a class definition - this is where method definitions are specifi...
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
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.
bool commit(const Commit &commit)
static bool isEqual(const EditEntry &LHS, const EditEntry &RHS)
param_const_iterator param_begin() const
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
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.
SourceManager & getSourceManager()
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 ...
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
Preprocessor & getPreprocessor() const
Return the current preprocessor.
Reading or writing from this object requires a barrier call.
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.
const ObjCPropertyDecl * findPropertyDecl(bool CheckOverrides=true) const
Returns the property associated with this method's selector.
TranslationUnitDecl * getTranslationUnitDecl() const
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
ObjCPropertyImplDecl * FindPropertyImplDecl(IdentifierInfo *propertyId, ObjCPropertyQueryKind queryKind) const
FindPropertyImplDecl - This method looks up a previous ObjCPropertyImplDecl added to the list of thos...
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
static bool versionsMatch(const VersionTuple &X, const VersionTuple &Y)
Check whether the two versions match.
static void rewriteToObjCProperty(const ObjCMethodDecl *Getter, const ObjCMethodDecl *Setter, const NSAPI &NS, edit::Commit &commit, unsigned LengthOfPrefix, bool Atomic, bool UseNsIosOnlyMacro, bool AvailabilityArgsMatch)
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
DiagnosticsEngine & getDiagnostics() const
Get the current diagnostics engine.
QualType getIntegerType() const
Return the integer type this enum decl corresponds to.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
bool insertBefore(SourceLocation loc, StringRef text)
static Decl::Kind getKind(const Decl *D)
The top declaration context.
Enable migration to NS_ENUM/NS_OPTIONS macros.
bool isPointerType() const
A trivial tuple used to represent a source range.
ObjCMethodDecl * getMethod(Selector Sel, bool isInstance, bool AllowHidden=false) const
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
bool isPropertyAccessor() const
bool isFunctionPointerType() const
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
SourceLocation getBegin() const
const LangOptions & getLangOpts() const
ObjCCategoryImplDecl - An object of this class encapsulates a category @implementation declaration...
void addPPCallbacks(std::unique_ptr< PPCallbacks > C)
This class handles loading and caching of source files into memory.
Attr - This represents one attribute.
SourceLocation getLocation() const
QualType getType() const
Return the type wrapped by this type source info.
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.
decl_iterator decls_end() const
Qualifiers::ObjCLifetime getObjCLifetime() const
Returns lifetime attribute of this type.
RetEffect summarizes a call's retain/release behavior with respect to its return value.