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;
107 llvm::StringSet<> WhiteListFilenames;
109 RetainSummaryManager &getSummaryManager(
ASTContext &Ctx) {
111 Summaries.reset(
new RetainSummaryManager(Ctx,
117 ObjCMigrateASTConsumer(StringRef migrateDir,
unsigned astMigrateActions,
122 : MigrateDir(migrateDir), ASTMigrateActions(astMigrateActions),
123 NSIntegerTypedefed(nullptr), NSUIntegerTypedefed(nullptr),
124 Remapper(remapper), FileMgr(fileMgr), PPRec(PPRec), PP(PP),
125 IsOutputFile(isOutputFile), FoundationIncluded(
false) {
127 for (
const std::string &Val : WhiteList)
128 WhiteListFilenames.insert(Val);
132 void Initialize(
ASTContext &Context)
override {
133 NSAPIObj.reset(
new NSAPI(Context));
147 void HandleTopLevelDeclInObjCContainer(
DeclGroupRef DG)
override {
148 ObjCMigrateASTConsumer::HandleTopLevelDecl(DG);
151 void HandleTranslationUnit(
ASTContext &Ctx)
override;
153 bool canModifyFile(StringRef Path) {
154 if (WhiteListFilenames.empty())
156 return WhiteListFilenames.find(llvm::sys::path::filename(Path))
157 != WhiteListFilenames.end();
162 return canModifyFile(FE->getName());
164 bool canModifyFile(
FileID FID) {
170 bool canModify(
const Decl *D) {
174 return canModify(CatImpl->getCategoryDecl());
176 return canModify(Impl->getClassInterface());
178 return canModify(cast<Decl>(MD->getDeclContext()));
181 return canModifyFile(FID);
188 std::unique_ptr<FrontendAction> WrappedAction, StringRef migrateDir,
189 unsigned migrateAction)
191 ObjCMigAction(migrateAction), CompInst(nullptr) {
192 if (MigrateDir.empty())
196 std::unique_ptr<ASTConsumer>
201 std::vector<std::unique_ptr<ASTConsumer>> Consumers;
203 Consumers.push_back(std::make_unique<ObjCMigrateASTConsumer>(
204 MigrateDir, ObjCMigAction, Remapper, CompInst->
getFileManager(), PPRec,
206 return std::make_unique<MultiplexConsumer>(std::move(Consumers));
221 return !(isa<ArraySubscriptExpr>(
Expr) || isa<CallExpr>(
Expr) ||
222 isa<DeclRefExpr>(
Expr) || isa<CXXNamedCastExpr>(
Expr) ||
223 isa<CXXConstructExpr>(
Expr) || isa<CXXThisExpr>(
Expr) ||
224 isa<CXXTypeidExpr>(
Expr) ||
225 isa<CXXUnresolvedConstructExpr>(
Expr) ||
226 isa<ObjCMessageExpr>(
Expr) || isa<ObjCPropertyRefExpr>(
Expr) ||
227 isa<ObjCProtocolExpr>(
Expr) || isa<MemberExpr>(
Expr) ||
228 isa<ObjCIvarRefExpr>(
Expr) || isa<ParenExpr>(
FullExpr) ||
229 isa<ParenListExpr>(
Expr) || isa<SizeOfPackExpr>(
Expr));
243 if (Receiver->getType()->isObjCBuiltinType())
257 bool ReceiverIsSuper =
271 std::string PropertyDotString;
276 PropertyDotString =
").";
279 PropertyDotString =
".";
280 PropertyDotString += Prop->
getName();
281 commit.
replace(SpaceRange, PropertyDotString);
289 std::string PropertyDotString =
".";
290 PropertyDotString += Prop->
getName();
291 PropertyDotString +=
" =";
293 const Expr *RHS = Args[0];
303 if (colon && colon[0] ==
':')
304 PropertyDotString +=
" ";
315 ObjCMigrateASTConsumer &Consumer;
319 ObjCMigrator(ObjCMigrateASTConsumer &consumer,
ParentMap &PMap)
320 : Consumer(consumer), PMap(PMap) { }
322 bool shouldVisitTemplateInstantiations()
const {
return false; }
323 bool shouldWalkTypesOfTypeLocs()
const {
return false; }
329 Consumer.Editor->commit(commit);
335 Consumer.Editor->commit(commit);
340 rewriteToPropertyDotSyntax(E, Consumer.PP, *Consumer.NSAPIObj,
342 Consumer.Editor->commit(commit);
352 if (!TraverseStmt(SubStmt))
355 return WalkUpFromObjCMessageExpr(E);
360 ObjCMigrateASTConsumer &Consumer;
361 std::unique_ptr<ParentMap> PMap;
364 BodyMigrator(ObjCMigrateASTConsumer &consumer) : Consumer(consumer) { }
366 bool shouldVisitTemplateInstantiations()
const {
return false; }
367 bool shouldWalkTypesOfTypeLocs()
const {
return false; }
369 bool TraverseStmt(
Stmt *S) {
371 ObjCMigrator(Consumer, *PMap).TraverseStmt(S);
377 void ObjCMigrateASTConsumer::migrateDecl(
Decl *D) {
380 if (isa<ObjCMethodDecl>(D))
383 BodyMigrator(*this).TraverseDecl(D);
386 static void append_attr(std::string &PropertyString,
const char *attr,
389 PropertyString +=
"(";
393 PropertyString +=
", ";
394 PropertyString += attr;
399 const std::string& TypeString,
401 const char *argPtr = TypeString.c_str();
406 PropertyString += *argPtr;
410 PropertyString += *argPtr;
415 PropertyString += (*argPtr);
417 PropertyString +=
name;
422 PropertyString += *argPtr;
432 if (RetainableObject &&
450 else if (RetainableObject)
458 unsigned LengthOfPrefix,
459 bool Atomic,
bool UseNsIosOnlyMacro,
460 bool AvailabilityArgsMatch) {
462 bool LParenAdded =
false;
463 std::string PropertyString =
"@property ";
464 if (UseNsIosOnlyMacro && NS.
isMacroDefined(
"NS_NONATOMIC_IOSONLY")) {
465 PropertyString +=
"(NS_NONATOMIC_IOSONLY";
467 }
else if (!Atomic) {
468 PropertyString +=
"(nonatomic";
473 StringRef PropertyName(PropertyNameString);
474 if (LengthOfPrefix > 0) {
476 PropertyString +=
"(getter=";
480 PropertyString +=
", getter=";
481 PropertyString += PropertyNameString;
485 append_attr(PropertyString,
"readonly", LParenAdded);
490 if (PropertyName.equals(
"target") ||
491 (PropertyName.find(
"delegate") != StringRef::npos) ||
492 (PropertyName.find(
"dataSource") != StringRef::npos)) {
495 append_attr(PropertyString,
"assign", LParenAdded);
496 }
else if (!Setter) {
499 append_attr(PropertyString, MemoryManagementAttr, LParenAdded);
504 append_attr(PropertyString, MemoryManagementAttr, LParenAdded);
507 PropertyString +=
')';
509 if (!isa<TypedefType>(RT)) {
518 PropertyString +=
" ";
521 SubPolicy.SuppressLifetimeQualifiers =
true;
522 std::string TypeString = RT.
getAsString(SubPolicy);
523 if (LengthOfPrefix > 0) {
526 StringRef PropertyNameStringRef(PropertyNameString);
527 PropertyNameStringRef = PropertyNameStringRef.drop_front(LengthOfPrefix);
528 PropertyNameString = std::string(PropertyNameStringRef);
529 bool NoLowering = (
isUppercase(PropertyNameString[0]) &&
530 PropertyNameString.size() > 1 &&
533 PropertyNameString[0] =
toLowercase(PropertyNameString[0]);
538 PropertyNameString.c_str());
540 char LastChar = TypeString[TypeString.size()-1];
541 PropertyString += TypeString;
543 PropertyString +=
' ';
544 PropertyString += PropertyNameString;
552 EndGetterSelectorLoc),
554 if (Setter && AvailabilityArgsMatch) {
568 StringRef Name = CatDecl->getName();
569 return Name.endswith(
"Deprecated");
574 void ObjCMigrateASTConsumer::migrateObjCContainerDecl(
ASTContext &Ctx,
579 for (
auto *Method : D->
methods()) {
582 bool PropertyInferred = migrateProperty(Ctx, D, Method);
586 if (!PropertyInferred ||
589 migrateNsReturnsInnerPointer(Ctx, Method);
597 migratePropertyNsReturnsInnerPointer(Ctx, Prop);
609 bool HasAtleastOneRequiredProperty =
false;
611 for (
const auto *
Property : PDecl->instance_properties()) {
614 HasAtleastOneRequiredProperty =
true;
621 Property->getDeclName().getAsIdentifierInfo(),
625 else if (
ObjCPropertyDecl *ClassProperty = dyn_cast<ObjCPropertyDecl>(R[0])) {
626 if ((ClassProperty->getPropertyAttributes()
627 !=
Property->getPropertyAttributes()) ||
638 bool HasAtleastOneRequiredMethod =
false;
640 if (PDecl->meth_begin() == PDecl->meth_end())
641 return HasAtleastOneRequiredProperty;
642 for (
const auto *MD : PDecl->methods()) {
643 if (MD->isImplicit())
651 HasAtleastOneRequiredMethod =
true;
652 for (
unsigned I = 0, N = R.
size(); I != N; ++I)
662 return HasAtleastOneRequiredProperty || HasAtleastOneRequiredMethod;
669 std::string ClassString;
673 if (Protocols.
empty()) {
675 for (
unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
676 ClassString += ConformingProtocols[i]->getNameAsString();
684 for (
unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
685 ClassString += ConformingProtocols[i]->getNameAsString();
698 StringRef UnsignedName = llvm::StringSwitch<StringRef>(NSIntegerName)
699 .Case(
"int8_t",
"uint8_t")
700 .Case(
"int16_t",
"uint16_t")
701 .Case(
"int32_t",
"uint32_t")
702 .Case(
"NSInteger",
"NSUInteger")
703 .Case(
"int64_t",
"uint64_t")
704 .Default(NSIntegerName);
711 StringRef NSIntegerName,
713 std::string ClassString;
715 ClassString =
"typedef NS_OPTIONS(";
719 ClassString =
"typedef NS_ENUM(";
720 ClassString += NSIntegerName;
727 commit.
replace(R, ClassString);
731 if (EndOfEnumDclLoc.
isValid()) {
741 if (EndTypedefDclLoc.
isValid()) {
751 if (EndOfEnumDclLoc.
isValid()) {
766 bool IsNSIntegerType) {
768 assert(!DesignatedEnumType.
isNull()
769 &&
"rewriteToNSMacroDecl - underlying enum type is null");
772 std::string TypeString = DesignatedEnumType.
getAsString(Policy);
773 std::string ClassString = IsNSIntegerType ?
"NS_ENUM(" :
"NS_OPTIONS(";
774 ClassString += TypeString;
784 commit.
replace(R, ClassString);
795 bool PowerOfTwo =
true;
796 bool AllHexdecimalEnumerator =
true;
797 uint64_t MaxPowerOfTwoVal = 0;
799 const Expr *InitExpr = Enumerator->getInitExpr();
802 AllHexdecimalEnumerator =
false;
806 if (
const BinaryOperator *BO = dyn_cast<BinaryOperator>(InitExpr))
807 if (BO->isShiftOp() || BO->isBitwiseOp())
810 uint64_t EnumVal = Enumerator->getInitVal().getZExtValue();
811 if (PowerOfTwo && EnumVal) {
812 if (!llvm::isPowerOf2_64(EnumVal))
814 else if (EnumVal > MaxPowerOfTwoVal)
815 MaxPowerOfTwoVal = EnumVal;
817 if (AllHexdecimalEnumerator && EnumVal) {
818 bool FoundHexdecimalEnumerator =
false;
822 if (
Tok.isLiteral() &&
Tok.getLength() > 2) {
823 if (
const char *StringLit =
Tok.getLiteralData())
824 FoundHexdecimalEnumerator =
825 (StringLit[0] ==
'0' && (
toLowercase(StringLit[1]) ==
'x'));
827 if (!FoundHexdecimalEnumerator)
828 AllHexdecimalEnumerator =
false;
831 return AllHexdecimalEnumerator || (PowerOfTwo && (MaxPowerOfTwoVal > 2));
834 void ObjCMigrateASTConsumer::migrateProtocolConformance(
ASTContext &Ctx,
837 if (!IDecl || ObjCProtocolDecls.empty() || IDecl->
isDeprecated())
846 if (!ExplicitProtocols.count(ProtDecl))
847 PotentialImplicitProtocols.push_back(ProtDecl);
849 if (PotentialImplicitProtocols.empty())
856 for (
unsigned i = 0, e = PotentialImplicitProtocols.size(); i != e; i++)
858 PotentialImplicitProtocols[i]))
859 ConformingProtocols.push_back(PotentialImplicitProtocols[i]);
861 if (ConformingProtocols.empty())
867 for (
unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
870 for (
unsigned i1 = 0, e1 = ConformingProtocols.size(); i1 != e1; i1++) {
872 if (PDecl == TargetPDecl)
881 MinimalConformingProtocols.push_back(TargetPDecl);
883 if (MinimalConformingProtocols.empty())
888 Editor->commit(commit);
891 void ObjCMigrateASTConsumer::CacheObjCNSIntegerTypedefed(
895 if (NSAPIObj->isObjCNSIntegerType(qt))
896 NSIntegerTypedefed = TypedefDcl;
897 else if (NSAPIObj->isObjCNSUIntegerType(qt))
898 NSUIntegerTypedefed = TypedefDcl;
901 bool ObjCMigrateASTConsumer::migrateNSEnumDecl(
ASTContext &Ctx,
908 if (NSIntegerTypedefed) {
909 TypedefDcl = NSIntegerTypedefed;
910 NSIntegerTypedefed =
nullptr;
912 else if (NSUIntegerTypedefed) {
913 TypedefDcl = NSUIntegerTypedefed;
914 NSUIntegerTypedefed =
nullptr;
918 FileID FileIdOfTypedefDcl =
922 if (FileIdOfTypedefDcl != FileIdOfEnumDcl)
929 StringRef NSIntegerName = NSAPIObj->GetNSIntegralKind(qt);
931 if (NSIntegerName.empty()) {
934 if (EnumTy->getDecl() == EnumDcl) {
936 if (!InsertFoundation(Ctx, TypedefDcl->
getBeginLoc()))
940 Editor->commit(commit);
949 if (!InsertFoundation(Ctx, TypedefDcl->
getBeginLoc()))
953 commit, NSIntegerName, NSOptions);
954 Editor->commit(commit);
959 const ObjCMigrateASTConsumer &ASTC,
965 std::string ClassString;
967 TypeLoc TL = TSInfo->getTypeLoc();
969 ClassString =
"instancetype";
974 ClassString +=
" (instancetype)";
977 commit.
replace(R, ClassString);
978 ASTC.Editor->commit(commit);
985 std::string ClassString;
987 TypeLoc TL = TSInfo->getTypeLoc();
989 ClassString = std::string(IDecl->
getName());
996 ClassString += IDecl->
getName(); ClassString +=
"*)";
999 commit.
replace(R, ClassString);
1000 ASTC.Editor->commit(commit);
1003 void ObjCMigrateASTConsumer::migrateMethodInstanceType(
ASTContext &Ctx,
1009 std::string ClassName;
1010 switch (OIT_Family) {
1012 migrateFactoryMethod(Ctx, CDecl, OM);
1015 ClassName =
"NSArray";
1018 ClassName =
"NSDictionary";
1037 IDecl = CatDecl->getClassInterface();
1038 else if (
ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(CDecl))
1043 migrateFactoryMethod(Ctx, CDecl, OM);
1060 T = TD->getDecl()->getUnderlyingType();
1065 if (UPointeeT->isRecordType()) {
1084 const AvailabilityAttr *AA1 = dyn_cast<AvailabilityAttr>(At1);
1087 const AvailabilityAttr *AA2 = cast<AvailabilityAttr>(At2);
1089 VersionTuple Introduced1 = AA1->getIntroduced();
1090 VersionTuple Deprecated1 = AA1->getDeprecated();
1091 VersionTuple Obsoleted1 = AA1->getObsoleted();
1092 bool IsUnavailable1 = AA1->getUnavailable();
1093 VersionTuple Introduced2 = AA2->getIntroduced();
1094 VersionTuple Deprecated2 = AA2->getDeprecated();
1095 VersionTuple Obsoleted2 = AA2->getObsoleted();
1096 bool IsUnavailable2 = AA2->getUnavailable();
1100 IsUnavailable1 == IsUnavailable2);
1104 bool &AvailabilityArgsMatch) {
1106 for (
unsigned i = 0, e = Attrs1.size(); i != e; i++) {
1108 for (
unsigned j = 0, f = Attrs2.size(); j != f; j++) {
1112 if (Attrs1[i]->
getKind() == Attrs2[j]->getKind()) {
1113 if (AvailabilityArgsMatch)
1133 bool &AvailabilityArgsMatch) {
1138 AvailabilityArgsMatch =
true;
1142 if (
match && (Attrs2.size() > Attrs1.size()))
1151 std::string NameString = Name;
1157 bool ObjCMigrateASTConsumer::migrateProperty(
ASTContext &Ctx,
1181 unsigned LengthOfPrefix = 0;
1182 if (!SetterMethod) {
1184 StringRef getterNameString = getterName->
getName();
1185 bool IsPrefix = getterNameString.startswith(
"is");
1190 if (IsPrefix || getterNameString.startswith(
"get")) {
1191 LengthOfPrefix = (IsPrefix ? 2 : 3);
1192 const char *CGetterName = getterNameString.data() + LengthOfPrefix;
1197 if (CGetterName[0] &&
isUppercase(CGetterName[0])) {
1198 getterName = &Ctx.
Idents.
get(CGetterName);
1211 bool AvailabilityArgsMatch;
1212 if (SetterMethod->isDeprecated() ||
1217 QualType SRT = SetterMethod->getReturnType();
1220 const ParmVarDecl *argDecl = *SetterMethod->param_begin();
1227 (ASTMigrateActions &
1229 (ASTMigrateActions &
1231 AvailabilityArgsMatch);
1232 Editor->commit(commit);
1241 (ASTMigrateActions &
1243 (ASTMigrateActions &
1246 Editor->commit(commit);
1252 void ObjCMigrateASTConsumer::migrateNsReturnsInnerPointer(
ASTContext &Ctx,
1256 OM->
hasAttr<ObjCReturnsInnerPointerAttr>())
1261 !NSAPIObj->isMacroDefined(
"NS_RETURNS_INNER_POINTER"))
1266 Editor->commit(commit);
1269 void ObjCMigrateASTConsumer::migratePropertyNsReturnsInnerPointer(
ASTContext &Ctx,
1274 !NSAPIObj->isMacroDefined(
"NS_RETURNS_INNER_POINTER"))
1277 commit.
insertBefore(
P->getEndLoc(),
" NS_RETURNS_INNER_POINTER ");
1278 Editor->commit(commit);
1281 void ObjCMigrateASTConsumer::migrateAllMethodInstaceType(
ASTContext &Ctx,
1287 for (
auto *Method : CDecl->
methods()) {
1290 migrateMethodInstanceType(Ctx, CDecl, Method);
1294 void ObjCMigrateASTConsumer::migrateFactoryMethod(
ASTContext &Ctx,
1308 IDecl = CatDecl->getClassInterface();
1309 else if (
ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(CDecl))
1315 std::string StringClassName = std::string(IDecl->
getName());
1316 StringRef LoweredClassName(StringClassName);
1317 std::string StringLoweredClassName = LoweredClassName.lower();
1318 LoweredClassName = StringLoweredClassName;
1325 std::string MethodName = std::string(MethodIdName->
getName());
1327 StringRef STRefMethodName(MethodName);
1329 if (STRefMethodName.startswith(
"standard"))
1330 len = strlen(
"standard");
1331 else if (STRefMethodName.startswith(
"shared"))
1332 len = strlen(
"shared");
1333 else if (STRefMethodName.startswith(
"default"))
1334 len = strlen(
"default");
1337 MethodName = std::string(STRefMethodName.substr(len));
1339 std::string MethodNameSubStr = MethodName.substr(0, 3);
1340 StringRef MethodNamePrefix(MethodNameSubStr);
1341 std::string StringLoweredMethodNamePrefix = MethodNamePrefix.lower();
1342 MethodNamePrefix = StringLoweredMethodNamePrefix;
1343 size_t Ix = LoweredClassName.rfind(MethodNamePrefix);
1344 if (Ix == StringRef::npos)
1346 std::string ClassNamePostfix = std::string(LoweredClassName.substr(Ix));
1347 StringRef LoweredMethodName(MethodName);
1348 std::string StringLoweredMethodName = LoweredMethodName.lower();
1349 LoweredMethodName = StringLoweredMethodName;
1350 if (!LoweredMethodName.startswith(ClassNamePostfix))
1363 Ty = TD->getDecl()->getUnderlyingType();
1389 void ObjCMigrateASTConsumer::AnnotateImplicitBridging(
ASTContext &Ctx) {
1390 if (CFFunctionIBCandidates.empty())
1392 if (!NSAPIObj->isMacroDefined(
"CF_IMPLICIT_BRIDGING_ENABLED")) {
1393 CFFunctionIBCandidates.clear();
1398 const Decl *FirstFD = CFFunctionIBCandidates[0];
1399 const Decl *LastFD =
1400 CFFunctionIBCandidates[CFFunctionIBCandidates.size()-1];
1401 const char *PragmaString =
"\nCF_IMPLICIT_BRIDGING_ENABLED\n\n";
1404 PragmaString =
"\n\nCF_IMPLICIT_BRIDGING_DISABLED\n";
1408 if (isa<FunctionDecl>(LastFD)) {
1415 EndLoc =
Tok.getLocation();
1418 Editor->commit(commit);
1420 CFFunctionIBCandidates.clear();
1423 void ObjCMigrateASTConsumer::migrateCFAnnotation(
ASTContext &Ctx,
const Decl *
Decl) {
1428 assert(CFFunctionIBCandidates.empty() &&
1429 "Cannot have audited functions/methods inside user " 1430 "provided CF_IMPLICIT_BRIDGING_ENABLE");
1436 CF_BRIDGING_KIND AuditKind = migrateAddFunctionAnnotation(Ctx, FuncDecl);
1437 if (AuditKind == CF_BRIDGING_ENABLE) {
1438 CFFunctionIBCandidates.push_back(
Decl);
1442 else if (AuditKind == CF_BRIDGING_MAY_INCLUDE) {
1443 if (!CFFunctionIBCandidates.empty()) {
1444 CFFunctionIBCandidates.push_back(
Decl);
1450 AnnotateImplicitBridging(Ctx);
1453 migrateAddMethodAnnotation(Ctx, cast<ObjCMethodDecl>(
Decl));
1454 AnnotateImplicitBridging(Ctx);
1458 void ObjCMigrateASTConsumer::AddCFAnnotations(
ASTContext &Ctx,
1459 const RetainSummary *RS,
1461 bool ResultAnnotated) {
1463 if (!ResultAnnotated) {
1465 const char *AnnotationString =
nullptr;
1466 if (
Ret.getObjKind() == ObjKind::CF) {
1467 if (
Ret.isOwned() && NSAPIObj->isMacroDefined(
"CF_RETURNS_RETAINED"))
1468 AnnotationString =
" CF_RETURNS_RETAINED";
1469 else if (
Ret.notOwned() &&
1470 NSAPIObj->isMacroDefined(
"CF_RETURNS_NOT_RETAINED"))
1471 AnnotationString =
" CF_RETURNS_NOT_RETAINED";
1474 if (
Ret.isOwned() && NSAPIObj->isMacroDefined(
"NS_RETURNS_RETAINED"))
1475 AnnotationString =
" NS_RETURNS_RETAINED";
1478 if (AnnotationString) {
1481 Editor->commit(commit);
1486 pe = FuncDecl->
param_end(); pi != pe; ++pi, ++i) {
1490 !pd->
hasAttr<CFConsumedAttr>() &&
1491 NSAPIObj->isMacroDefined(
"CF_CONSUMED")) {
1494 Editor->commit(commit);
1496 !pd->
hasAttr<NSConsumedAttr>() &&
1497 NSAPIObj->isMacroDefined(
"NS_CONSUMED")) {
1500 Editor->commit(commit);
1505 ObjCMigrateASTConsumer::CF_BRIDGING_KIND
1506 ObjCMigrateASTConsumer::migrateAddFunctionAnnotation(
1510 return CF_BRIDGING_NONE;
1512 const RetainSummary *RS =
1513 getSummaryManager(Ctx).getSummary(AnyCall(FuncDecl));
1514 bool FuncIsReturnAnnotated = (FuncDecl->
hasAttr<CFReturnsRetainedAttr>() ||
1515 FuncDecl->
hasAttr<CFReturnsNotRetainedAttr>() ||
1516 FuncDecl->
hasAttr<NSReturnsRetainedAttr>() ||
1517 FuncDecl->
hasAttr<NSReturnsNotRetainedAttr>() ||
1518 FuncDecl->
hasAttr<NSReturnsAutoreleasedAttr>());
1521 if (FuncIsReturnAnnotated && FuncDecl->
getNumParams() == 0)
1522 return CF_BRIDGING_NONE;
1524 bool ReturnCFAudited =
false;
1525 if (!FuncIsReturnAnnotated) {
1527 if (
Ret.getObjKind() == ObjKind::CF &&
1528 (
Ret.isOwned() ||
Ret.notOwned()))
1529 ReturnCFAudited =
true;
1531 return CF_BRIDGING_NONE;
1536 bool ArgCFAudited =
false;
1538 pe = FuncDecl->
param_end(); pi != pe; ++pi, ++i) {
1544 ArgCFAudited =
true;
1546 ArgCFAudited =
true;
1550 AddCFAnnotations(Ctx, RS, FuncDecl, FuncIsReturnAnnotated);
1551 return CF_BRIDGING_NONE;
1555 if (ReturnCFAudited || ArgCFAudited)
1556 return CF_BRIDGING_ENABLE;
1558 return CF_BRIDGING_MAY_INCLUDE;
1561 void ObjCMigrateASTConsumer::migrateARCSafeAnnotation(
ASTContext &Ctx,
1563 if (!isa<ObjCInterfaceDecl>(CDecl) || CDecl->
isDeprecated())
1567 for (
const auto *Method : CDecl->
methods())
1568 migrateCFAnnotation(Ctx, Method);
1571 void ObjCMigrateASTConsumer::AddCFAnnotations(
ASTContext &Ctx,
1572 const RetainSummary *RS,
1574 bool ResultAnnotated) {
1576 if (!ResultAnnotated) {
1578 const char *AnnotationString =
nullptr;
1579 if (
Ret.getObjKind() == ObjKind::CF) {
1580 if (
Ret.isOwned() && NSAPIObj->isMacroDefined(
"CF_RETURNS_RETAINED"))
1581 AnnotationString =
" CF_RETURNS_RETAINED";
1582 else if (
Ret.notOwned() &&
1583 NSAPIObj->isMacroDefined(
"CF_RETURNS_NOT_RETAINED"))
1584 AnnotationString =
" CF_RETURNS_NOT_RETAINED";
1597 if (
Ret.isOwned() && NSAPIObj->isMacroDefined(
"NS_RETURNS_RETAINED"))
1598 AnnotationString =
" NS_RETURNS_RETAINED";
1603 if (AnnotationString) {
1606 Editor->commit(commit);
1611 pe = MethodDecl->
param_end(); pi != pe; ++pi, ++i) {
1616 && !pd->
hasAttr<CFConsumedAttr>() &&
1617 NSAPIObj->isMacroDefined(
"CF_CONSUMED")) {
1620 Editor->commit(commit);
1625 void ObjCMigrateASTConsumer::migrateAddMethodAnnotation(
1631 const RetainSummary *RS =
1632 getSummaryManager(Ctx).getSummary(AnyCall(MethodDecl));
1634 bool MethodIsReturnAnnotated =
1635 (MethodDecl->
hasAttr<CFReturnsRetainedAttr>() ||
1636 MethodDecl->
hasAttr<CFReturnsNotRetainedAttr>() ||
1637 MethodDecl->
hasAttr<NSReturnsRetainedAttr>() ||
1638 MethodDecl->
hasAttr<NSReturnsNotRetainedAttr>() ||
1639 MethodDecl->
hasAttr<NSReturnsAutoreleasedAttr>());
1641 if (RS->getReceiverEffect().getKind() ==
DecRef &&
1642 !MethodDecl->
hasAttr<NSConsumesSelfAttr>() &&
1645 NSAPIObj->isMacroDefined(
"NS_CONSUMES_SELF")) {
1648 Editor->commit(commit);
1652 if (MethodIsReturnAnnotated &&
1656 if (!MethodIsReturnAnnotated) {
1658 if ((
Ret.getObjKind() == ObjKind::CF ||
1660 (
Ret.isOwned() ||
Ret.notOwned())) {
1661 AddCFAnnotations(Ctx, RS, MethodDecl,
false);
1670 pe = MethodDecl->
param_end(); pi != pe; ++pi, ++i) {
1675 AddCFAnnotations(Ctx, RS, MethodDecl, MethodIsReturnAnnotated);
1684 bool shouldVisitTemplateInstantiations()
const {
return false; }
1685 bool shouldWalkTypesOfTypeLocs()
const {
return false; }
1698 return !SuperInitChecker().TraverseStmt(MD->
getBody());
1701 void ObjCMigrateASTConsumer::inferDesignatedInitializers(
1708 if (!NSAPIObj->isMacroDefined(
"NS_DESIGNATED_INITIALIZER"))
1712 if (MD->isDeprecated() ||
1713 MD->getMethodFamily() !=
OMF_init ||
1714 MD->isDesignatedInitializerForTheInterface())
1723 Editor->commit(commit);
1728 bool ObjCMigrateASTConsumer::InsertFoundation(
ASTContext &Ctx,
1730 if (FoundationIncluded)
1732 if (
Loc.isInvalid())
1734 auto *nsEnumId = &Ctx.
Idents.
get(
"NS_ENUM");
1736 FoundationIncluded =
true;
1741 commit.
insert(
Loc,
"#ifndef NS_ENUM\n@import Foundation;\n#endif\n");
1743 commit.
insert(
Loc,
"#ifndef NS_ENUM\n#import <Foundation/Foundation.h>\n#endif\n");
1744 Editor->commit(commit);
1745 FoundationIncluded =
true;
1767 llvm::raw_ostream &
OS;
1771 : SourceMgr(
SM),
OS(
OS) {
1774 ~JSONEditWriter()
override {
OS <<
"]\n"; }
1777 struct EntryWriter {
1779 llvm::raw_ostream &
OS;
1782 : SourceMgr(
SM),
OS(
OS) {
1796 llvm::sys::fs::make_absolute(Path);
1797 OS <<
" \"file\": \"";
1798 OS.write_escaped(Path.str()) <<
"\",\n";
1799 OS <<
" \"offset\": " <<
Offset <<
",\n";
1803 assert(
Range.isCharRange());
1804 std::pair<FileID, unsigned>
Begin =
1806 std::pair<FileID, unsigned>
End =
1809 assert(
Begin.second <=
End.second);
1810 unsigned Length =
End.second -
Begin.second;
1812 OS <<
" \"remove\": " << Length <<
",\n";
1815 void writeText(StringRef
Text) {
1816 OS <<
" \"text\": \"";
1817 OS.write_escaped(
Text) <<
"\",\n";
1822 EntryWriter Writer(SourceMgr, OS);
1823 Writer.writeLoc(
Loc);
1824 Writer.writeText(
Text);
1828 EntryWriter Writer(SourceMgr, OS);
1829 Writer.writeLoc(
Range.getBegin());
1830 Writer.writeRemove(
Range);
1831 Writer.writeText(
Text);
1835 EntryWriter Writer(SourceMgr, OS);
1836 Writer.writeLoc(
Range.getBegin());
1837 Writer.writeRemove(
Range);
1843 void ObjCMigrateASTConsumer::HandleTranslationUnit(
ASTContext &Ctx) {
1851 if (FileId.
isValid() && FileId != FID) {
1853 AnnotateImplicitBridging(Ctx);
1857 if (canModify(CDecl))
1858 migrateObjCContainerDecl(Ctx, CDecl);
1860 if (canModify(CatDecl))
1861 migrateObjCContainerDecl(Ctx, CatDecl);
1865 if (canModify(PDecl))
1866 migrateObjCContainerDecl(Ctx, PDecl);
1869 dyn_cast<ObjCImplementationDecl>(*D)) {
1872 migrateProtocolConformance(Ctx, ImpDecl);
1874 else if (
const EnumDecl *ED = dyn_cast<EnumDecl>(*D)) {
1881 const TypedefDecl *TD = dyn_cast<TypedefDecl>(*N);
1882 if (migrateNSEnumDecl(Ctx, ED, TD) && TD)
1886 migrateNSEnumDecl(Ctx, ED,
nullptr);
1888 else if (
const TypedefDecl *TD = dyn_cast<TypedefDecl>(*D)) {
1896 if (
const EnumDecl *ED = dyn_cast<EnumDecl>(*N)) {
1897 if (canModify(ED)) {
1899 if (
const TypedefDecl *TDF = dyn_cast<TypedefDecl>(*N)) {
1901 if (migrateNSEnumDecl(Ctx, ED, TDF)) {
1903 CacheObjCNSIntegerTypedefed(TD);
1907 if (migrateNSEnumDecl(Ctx, ED, TD)) {
1913 CacheObjCNSIntegerTypedefed(TD);
1915 else if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(*D)) {
1918 migrateCFAnnotation(Ctx, FD);
1922 bool CanModify = canModify(CDecl);
1926 migrateAllMethodInstaceType(Ctx, CDecl);
1930 migrateARCSafeAnnotation(Ctx, CDecl);
1934 ImplD = dyn_cast<ObjCImplementationDecl>(*D)) {
1937 inferDesignatedInitializers(Ctx, ImplD);
1941 AnnotateImplicitBridging(Ctx);
1946 llvm::raw_fd_ostream
OS(MigrateDir, EC, llvm::sys::fs::OF_None);
1955 Editor->applyRewrites(Writer);
1960 RewritesReceiver Rec(rewriter);
1961 Editor->applyRewrites(Rec);
1964 I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) {
1970 llvm::raw_svector_ostream vecOS(newText);
1972 std::unique_ptr<llvm::MemoryBuffer> memBuf(
1973 llvm::MemoryBuffer::getMemBufferCopy(
1974 StringRef(newText.data(), newText.size()), file->getName()));
1977 Remapper.
remap(filePath.str(), std::move(memBuf));
1993 using namespace llvm::sys::fs;
1994 using namespace llvm::sys::path;
1996 std::vector<std::string> Filenames;
1997 if (DirPath.empty() || !is_directory(DirPath))
2001 directory_iterator DI = directory_iterator(DirPath, EC);
2002 directory_iterator DE;
2003 for (; !EC && DI != DE; DI = DI.increment(EC)) {
2004 if (is_regular_file(DI->path()))
2005 Filenames.push_back(std::string(filename(DI->path())));
2011 std::unique_ptr<ASTConsumer>
2016 unsigned ObjCMTOpts = ObjCMTAction;
2027 std::vector<std::string> WhiteList =
2029 return std::make_unique<ObjCMigrateASTConsumer>(
2039 unsigned RemoveLen = 0;
2048 Entry.Offset = unsigned(-1);
2053 Entry.Offset = unsigned(-2);
2060 static bool isEqual(
const EditEntry &LHS,
const EditEntry &RHS) {
2061 return LHS.File == RHS.File &&
2062 LHS.Offset == RHS.Offset &&
2063 LHS.RemoveLen == RHS.RemoveLen &&
2064 LHS.Text == RHS.Text;
2070 class RemapFileParser {
2074 RemapFileParser(
FileManager &FileMgr) : FileMgr(FileMgr) { }
2079 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
2080 llvm::MemoryBuffer::getFile(File);
2085 Stream YAMLStream(FileBufOrErr.get()->getMemBufferRef(),
SM);
2086 document_iterator I = YAMLStream.begin();
2087 if (I == YAMLStream.end())
2089 Node *Root = I->getRoot();
2093 SequenceNode *SeqNode = dyn_cast<SequenceNode>(Root);
2097 for (SequenceNode::iterator
2098 AI = SeqNode->begin(), AE = SeqNode->end(); AI != AE; ++AI) {
2099 MappingNode *MapNode = dyn_cast<MappingNode>(&*AI);
2102 parseEdit(MapNode, Entries);
2109 void parseEdit(llvm::yaml::MappingNode *
Node,
2113 bool Ignore =
false;
2115 for (MappingNode::iterator
2116 KVI =
Node->begin(), KVE =
Node->end(); KVI != KVE; ++KVI) {
2117 ScalarNode *KeyString = dyn_cast<ScalarNode>((*KVI).getKey());
2121 StringRef Key = KeyString->getValue(KeyStorage);
2123 ScalarNode *ValueString = dyn_cast<ScalarNode>((*KVI).getValue());
2127 StringRef Val = ValueString->getValue(ValueStorage);
2129 if (Key ==
"file") {
2134 }
else if (Key ==
"offset") {
2135 if (Val.getAsInteger(10, Entry.Offset))
2137 }
else if (Key ==
"remove") {
2138 if (Val.getAsInteger(10, Entry.RemoveLen))
2140 }
else if (Key ==
"text") {
2141 Entry.Text = std::string(Val);
2146 Entries.push_back(Entry);
2161 using namespace llvm::sys;
2168 I = Edits.begin(), E = Edits.end(); I != E; ++I) {
2169 const EditEntry &Entry = *I;
2170 assert(Entry.File == FE);
2172 SM.getLocForStartOfFile(FID).getLocWithOffset(Entry.Offset);
2174 if (Entry.RemoveLen != 0) {
2176 Loc.getLocWithOffset(Entry.RemoveLen));
2180 if (
Range.isInvalid()) {
2182 }
else if (Entry.Text.empty()) {
2191 RewritesReceiver Rec(rewriter);
2196 llvm::raw_svector_ostream
OS(NewText);
2201 if (fs::createTemporaryFile(path::filename(FE.
getName()),
2202 path::extension(FE.
getName()).drop_front(), FD,
2205 return std::string();
2208 llvm::raw_fd_ostream TmpOut(FD,
true);
2209 TmpOut.write(NewText.data(), NewText.size());
2212 return std::string(TempPath.str());
2216 std::vector<std::pair<std::string,std::string> > &remap,
2219 bool hasErrorOccurred =
false;
2223 RemapFileParser
Parser(FileMgr);
2228 DiagClient,
false));
2230 typedef llvm::DenseMap<FileEntryRef, std::vector<EditEntry> >
2232 FileEditEntriesTy FileEditEntries;
2237 I = remapFiles.begin(), E = remapFiles.end(); I != E; ++I) {
2239 if (
Parser.parse(*I, Entries))
2243 EI = Entries.begin(), EE = Entries.end(); EI != EE; ++EI) {
2244 EditEntry &Entry = *EI;
2247 std::pair<llvm::DenseSet<EditEntry>::iterator,
bool>
2248 Insert = EntriesSet.insert(Entry);
2252 FileEditEntries[*Entry.File].push_back(Entry);
2256 for (FileEditEntriesTy::iterator
2257 I = FileEditEntries.begin(), E = FileEditEntries.end(); I != E; ++I) {
2260 if (TempFile.empty()) {
2261 hasErrorOccurred =
true;
2265 remap.emplace_back(std::string(I->first.getName()), TempFile);
2268 return hasErrorOccurred;
std::string OutputFile
The output file, if any.
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)
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.
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
Specialize PointerLikeTypeTraits to allow LazyGenerationalUpdatePtr to be placed into a PointerUnion.
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.
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)
A reference to a FileEntry that includes the name of the file as it was accessed by the FileManager's...
StringRef getName() const
ArrayRef< ParmVarDecl * >::const_iterator param_const_iterator
param_const_iterator param_end() const
prefer 'atomic' property over 'nonatomic'.
SourceLocation getEndLoc() const
Get the end source location.
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
use NS_NONATOMIC_IOSONLY for property 'atomic' attribute
Enable migration to modern ObjC subscripting.
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.
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.
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.
ObjCProtocolDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this Objective-C protocol.
instprop_range instance_properties() const
One of these records is kept for each identifier that is lexed.
static ObjCInstanceTypeFamily getInstTypeMethodFamily(Selector sel)
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.
Optional< FileEntryRef > getFileEntryRefForID(FileID FID) const
Returns the FileEntryRef for the provided FileID.
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.
Enable migration to modern ObjC readwrite property.
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...
annotate property with NS_RETURNS_INNER_POINTER
unsigned SuppressStrongLifetime
When true, suppress printing of the __strong lifetime qualifier in ARC.
static void ReplaceWithInstancetype(ASTContext &Ctx, const ObjCMigrateASTConsumer &ASTC, ObjCMethodDecl *OM)
llvm::Optional< FileEntryRef > getOptionalFileRef(StringRef Filename, bool OpenFile=false, bool CacheFailure=true)
Get a FileEntryRef if it exists, without doing anything on error.
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...
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
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.
Enable migration to add conforming protocols.
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)
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.
bool isObjCBuiltinType() const
const T * castAs() const
Member-template castAs<specific type>.
ASTContext & getASTContext() const
bool isObjCRetainableType() const
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
SourceLocation getSelectorStartLoc() const
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
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.
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
Enable converting setter/getter expressions to property-dot syntx.
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)
Enable inferring NS_DESIGNATED_INITIALIZER for ObjC methods.
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
decl_iterator decls_begin() const
static unsigned getHashValue(const EditEntry &Val)
bool flushToDisk(StringRef outputDir, DiagnosticsEngine &Diag)
static bool Ret(InterpState &S, CodePtr &PC, APValue &Result)
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)
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.
SourceLocation getSuperLoc() const
Retrieve the location of the 'super' keyword for a class or instance message to 'super',...
ObjCInterfaceDecl * lookupInheritedClass(const IdentifierInfo *ICName)
lookupInheritedClass - This method returns ObjCInterfaceDecl * of the super class whose name is passe...
ObjCCategoryDecl - Represents a category declaration.
static bool AvailabilityAttrsMatch(Attr *At1, Attr *At2)
AvailabilityAttrsMatch - This routine checks that if comparing two availability attributes,...
SourceLocation getSelectorLoc(unsigned Index) const
bool isObjCObjectPointerType() const
bool isAnyPointerType() const
MacroDefinition getMacroDefinitionAtLoc(const IdentifierInfo *II, SourceLocation Loc)
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...
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 literals.
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)
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,...
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.
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.
Enable migration to modern ObjC readonly property.
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 of ObjC methods to 'instancetype'.
Enable annotation of ObjCMethods of all kinds.
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
static std::string applyEditsToTemp(FileEntryRef FE, ArrayRef< EditEntry > Edits, FileManager &FileMgr, DiagnosticsEngine &Diag)
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
We are substituting template parameters for (typically) other template parameters in order to rewrite...
QualType getType() const
Return the type wrapped by this type source info.
Enable migration to NS_ENUM/NS_OPTIONS macros.
std::pair< FileID, unsigned > getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
static bool rewriteToObjCInterfaceDecl(const ObjCInterfaceDecl *IDecl, llvm::SmallVectorImpl< ObjCProtocolDecl * > &ConformingProtocols, const NSAPI &NS, edit::Commit &commit)
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.