31 #include "llvm/ADT/SmallString.h" 32 #include "llvm/ADT/StringSet.h" 33 #include "llvm/Support/Path.h" 34 #include "llvm/Support/SourceMgr.h" 35 #include "llvm/Support/YAMLParser.h" 37 using namespace clang;
38 using namespace arcmt;
44 enum CF_BRIDGING_KIND {
47 CF_BRIDGING_MAY_INCLUDE
50 void migrateDecl(
Decl *D);
52 void migrateProtocolConformance(
ASTContext &Ctx,
54 void CacheObjCNSIntegerTypedefed(
const TypedefDecl *TypedefDcl);
68 void AddCFAnnotations(
ASTContext &Ctx,
const CallEffects &CE,
70 void AddCFAnnotations(
ASTContext &Ctx,
const CallEffects &CE,
73 void AnnotateImplicitBridging(
ASTContext &Ctx);
75 CF_BRIDGING_KIND migrateAddFunctionAnnotation(
ASTContext &Ctx,
80 void migrateAddMethodAnnotation(
ASTContext &Ctx,
83 void inferDesignatedInitializers(
ASTContext &Ctx,
89 std::string MigrateDir;
90 unsigned ASTMigrateActions;
94 std::unique_ptr<NSAPI> NSAPIObj;
95 std::unique_ptr<edit::EditedSource> Editor;
101 bool FoundationIncluded;
102 llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ObjCProtocolDecls;
104 llvm::StringSet<> WhiteListFilenames;
106 ObjCMigrateASTConsumer(StringRef migrateDir,
107 unsigned astMigrateActions,
114 : MigrateDir(migrateDir),
115 ASTMigrateActions(astMigrateActions),
116 NSIntegerTypedefed(nullptr), NSUIntegerTypedefed(nullptr),
117 Remapper(remapper), FileMgr(fileMgr), PPRec(PPRec), PP(PP),
118 IsOutputFile(isOutputFile),
119 FoundationIncluded(
false){
122 for (
const std::string &Val : WhiteList)
123 WhiteListFilenames.insert(Val);
127 void Initialize(
ASTContext &Context)
override {
128 NSAPIObj.reset(
new NSAPI(Context));
142 void HandleTopLevelDeclInObjCContainer(
DeclGroupRef DG)
override {
143 ObjCMigrateASTConsumer::HandleTopLevelDecl(DG);
146 void HandleTranslationUnit(
ASTContext &Ctx)
override;
148 bool canModifyFile(StringRef Path) {
149 if (WhiteListFilenames.empty())
151 return WhiteListFilenames.find(llvm::sys::path::filename(Path))
152 != WhiteListFilenames.end();
154 bool canModifyFile(
const FileEntry *FE) {
157 return canModifyFile(FE->
getName());
159 bool canModifyFile(
FileID FID) {
165 bool canModify(
const Decl *D) {
169 return canModify(CatImpl->getCategoryDecl());
171 return canModify(Impl->getClassInterface());
173 return canModify(cast<Decl>(MD->getDeclContext()));
176 return canModifyFile(FID);
183 std::unique_ptr<FrontendAction> WrappedAction,
184 StringRef migrateDir,
185 unsigned migrateAction)
187 ObjCMigAction(migrateAction),
189 if (MigrateDir.empty())
193 std::unique_ptr<ASTConsumer>
198 std::vector<std::unique_ptr<ASTConsumer>> Consumers;
200 Consumers.push_back(llvm::make_unique<ObjCMigrateASTConsumer>(
201 MigrateDir, ObjCMigAction, Remapper, CompInst->
getFileManager(), PPRec,
203 return llvm::make_unique<MultiplexConsumer>(std::move(Consumers));
218 return !(isa<ArraySubscriptExpr>(Expr) || isa<CallExpr>(Expr) ||
219 isa<DeclRefExpr>(Expr) || isa<CXXNamedCastExpr>(Expr) ||
220 isa<CXXConstructExpr>(Expr) || isa<CXXThisExpr>(Expr) ||
221 isa<CXXTypeidExpr>(Expr) ||
222 isa<CXXUnresolvedConstructExpr>(Expr) ||
223 isa<ObjCMessageExpr>(Expr) || isa<ObjCPropertyRefExpr>(Expr) ||
224 isa<ObjCProtocolExpr>(Expr) || isa<MemberExpr>(Expr) ||
225 isa<ObjCIvarRefExpr>(Expr) || isa<ParenExpr>(FullExpr) ||
226 isa<ParenListExpr>(Expr) || isa<SizeOfPackExpr>(Expr));
240 if (Receiver->getType()->isObjCBuiltinType())
254 bool ReceiverIsSuper =
268 std::string PropertyDotString;
273 PropertyDotString =
").";
276 PropertyDotString =
".";
277 PropertyDotString += Prop->
getName();
278 commit.
replace(SpaceRange, PropertyDotString);
286 std::string PropertyDotString =
".";
287 PropertyDotString += Prop->
getName();
288 PropertyDotString +=
" =";
290 const Expr *RHS = Args[0];
300 if (colon && colon[0] ==
':')
301 PropertyDotString +=
" ";
303 commit.
replace(Range, PropertyDotString);
312 ObjCMigrateASTConsumer &Consumer;
316 ObjCMigrator(ObjCMigrateASTConsumer &consumer,
ParentMap &PMap)
317 : Consumer(consumer), PMap(PMap) { }
319 bool shouldVisitTemplateInstantiations()
const {
return false; }
320 bool shouldWalkTypesOfTypeLocs()
const {
return false; }
326 Consumer.Editor->commit(commit);
332 Consumer.Editor->commit(commit);
337 rewriteToPropertyDotSyntax(E, Consumer.PP, *Consumer.NSAPIObj,
339 Consumer.Editor->commit(commit);
349 if (!TraverseStmt(SubStmt))
352 return WalkUpFromObjCMessageExpr(E);
357 ObjCMigrateASTConsumer &Consumer;
358 std::unique_ptr<ParentMap> PMap;
361 BodyMigrator(ObjCMigrateASTConsumer &consumer) : Consumer(consumer) { }
363 bool shouldVisitTemplateInstantiations()
const {
return false; }
364 bool shouldWalkTypesOfTypeLocs()
const {
return false; }
366 bool TraverseStmt(
Stmt *S) {
368 ObjCMigrator(Consumer, *PMap).TraverseStmt(S);
374 void ObjCMigrateASTConsumer::migrateDecl(
Decl *D) {
377 if (isa<ObjCMethodDecl>(D))
380 BodyMigrator(*this).TraverseDecl(D);
383 static void append_attr(std::string &PropertyString,
const char *attr,
386 PropertyString +=
"(";
390 PropertyString +=
", ";
391 PropertyString += attr;
396 const std::string& TypeString,
398 const char *argPtr = TypeString.c_str();
403 PropertyString += *argPtr;
407 PropertyString += *argPtr;
412 PropertyString += (*argPtr);
414 PropertyString += name;
419 PropertyString += *argPtr;
429 if (RetainableObject &&
447 else if (RetainableObject)
455 unsigned LengthOfPrefix,
456 bool Atomic,
bool UseNsIosOnlyMacro,
457 bool AvailabilityArgsMatch) {
459 bool LParenAdded =
false;
460 std::string PropertyString =
"@property ";
461 if (UseNsIosOnlyMacro && NS.
isMacroDefined(
"NS_NONATOMIC_IOSONLY")) {
462 PropertyString +=
"(NS_NONATOMIC_IOSONLY";
464 }
else if (!Atomic) {
465 PropertyString +=
"(nonatomic";
470 StringRef PropertyName(PropertyNameString);
471 if (LengthOfPrefix > 0) {
473 PropertyString +=
"(getter=";
477 PropertyString +=
", getter=";
478 PropertyString += PropertyNameString;
482 append_attr(PropertyString,
"readonly", LParenAdded);
487 if (PropertyName.equals(
"target") ||
488 (PropertyName.find(
"delegate") != StringRef::npos) ||
489 (PropertyName.find(
"dataSource") != StringRef::npos)) {
492 append_attr(PropertyString,
"assign", LParenAdded);
493 }
else if (!Setter) {
496 append_attr(PropertyString, MemoryManagementAttr, LParenAdded);
501 append_attr(PropertyString, MemoryManagementAttr, LParenAdded);
504 PropertyString +=
')';
506 if (!isa<TypedefType>(RT)) {
515 PropertyString +=
" ";
518 SubPolicy.SuppressLifetimeQualifiers =
true;
519 std::string TypeString = RT.
getAsString(SubPolicy);
520 if (LengthOfPrefix > 0) {
523 StringRef PropertyNameStringRef(PropertyNameString);
524 PropertyNameStringRef = PropertyNameStringRef.drop_front(LengthOfPrefix);
525 PropertyNameString = PropertyNameStringRef;
526 bool NoLowering = (
isUppercase(PropertyNameString[0]) &&
527 PropertyNameString.size() > 1 &&
530 PropertyNameString[0] =
toLowercase(PropertyNameString[0]);
535 PropertyNameString.c_str());
537 char LastChar = TypeString[TypeString.size()-1];
538 PropertyString += TypeString;
540 PropertyString +=
' ';
541 PropertyString += PropertyNameString;
549 EndGetterSelectorLoc),
551 if (Setter && AvailabilityArgsMatch) {
565 StringRef Name = CatDecl->getName();
566 return Name.endswith(
"Deprecated");
571 void ObjCMigrateASTConsumer::migrateObjCContainerDecl(
ASTContext &Ctx,
576 for (
auto *Method : D->
methods()) {
577 if (Method->isDeprecated())
579 bool PropertyInferred = migrateProperty(Ctx, D, Method);
583 if (!PropertyInferred ||
586 migrateNsReturnsInnerPointer(Ctx, Method);
593 !Prop->isDeprecated())
594 migratePropertyNsReturnsInnerPointer(Ctx, Prop);
606 bool HasAtleastOneRequiredProperty =
false;
608 for (
const auto *
Property : PDecl->instance_properties()) {
611 HasAtleastOneRequiredProperty =
true;
618 Property->getDeclName().getAsIdentifierInfo(),
622 else if (
ObjCPropertyDecl *ClassProperty = dyn_cast<ObjCPropertyDecl>(R[0])) {
623 if ((ClassProperty->getPropertyAttributes()
624 !=
Property->getPropertyAttributes()) ||
635 bool HasAtleastOneRequiredMethod =
false;
637 if (PDecl->meth_begin() == PDecl->meth_end())
638 return HasAtleastOneRequiredProperty;
639 for (
const auto *MD : PDecl->methods()) {
640 if (MD->isImplicit())
648 HasAtleastOneRequiredMethod =
true;
649 for (
unsigned I = 0, N = R.
size(); I != N; ++I)
659 return HasAtleastOneRequiredProperty || HasAtleastOneRequiredMethod;
666 std::string ClassString;
670 if (Protocols.
empty()) {
672 for (
unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
673 ClassString += ConformingProtocols[i]->getNameAsString();
681 for (
unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
682 ClassString += ConformingProtocols[i]->getNameAsString();
695 StringRef UnsignedName = llvm::StringSwitch<StringRef>(NSIntegerName)
696 .Case(
"int8_t",
"uint8_t")
697 .Case(
"int16_t",
"uint16_t")
698 .Case(
"int32_t",
"uint32_t")
699 .Case(
"NSInteger",
"NSUInteger")
700 .Case(
"int64_t",
"uint64_t")
701 .Default(NSIntegerName);
708 StringRef NSIntegerName,
710 std::string ClassString;
712 ClassString =
"typedef NS_OPTIONS(";
716 ClassString =
"typedef NS_ENUM(";
717 ClassString += NSIntegerName;
724 commit.
replace(R, ClassString);
728 if (EndOfEnumDclLoc.
isValid()) {
738 if (EndTypedefDclLoc.
isValid()) {
747 if (EndOfEnumDclLoc.
isValid()) {
762 bool IsNSIntegerType) {
764 assert(!DesignatedEnumType.
isNull()
765 &&
"rewriteToNSMacroDecl - underlying enum type is null");
768 std::string TypeString = DesignatedEnumType.
getAsString(Policy);
769 std::string ClassString = IsNSIntegerType ?
"NS_ENUM(" :
"NS_OPTIONS(";
770 ClassString += TypeString;
779 commit.
replace(R, ClassString);
790 bool PowerOfTwo =
true;
791 bool AllHexdecimalEnumerator =
true;
792 uint64_t MaxPowerOfTwoVal = 0;
794 const Expr *InitExpr = Enumerator->getInitExpr();
797 AllHexdecimalEnumerator =
false;
801 if (
const BinaryOperator *BO = dyn_cast<BinaryOperator>(InitExpr))
802 if (BO->isShiftOp() || BO->isBitwiseOp())
805 uint64_t EnumVal = Enumerator->getInitVal().getZExtValue();
806 if (PowerOfTwo && EnumVal) {
807 if (!llvm::isPowerOf2_64(EnumVal))
809 else if (EnumVal > MaxPowerOfTwoVal)
810 MaxPowerOfTwoVal = EnumVal;
812 if (AllHexdecimalEnumerator && EnumVal) {
813 bool FoundHexdecimalEnumerator =
false;
819 FoundHexdecimalEnumerator =
820 (StringLit[0] ==
'0' && (
toLowercase(StringLit[1]) ==
'x'));
822 if (!FoundHexdecimalEnumerator)
823 AllHexdecimalEnumerator =
false;
826 return AllHexdecimalEnumerator || (PowerOfTwo && (MaxPowerOfTwoVal > 2));
829 void ObjCMigrateASTConsumer::migrateProtocolConformance(
ASTContext &Ctx,
832 if (!IDecl || ObjCProtocolDecls.empty() || IDecl->
isDeprecated())
836 llvm::SmallPtrSet<ObjCProtocolDecl *, 8> ExplicitProtocols;
841 if (!ExplicitProtocols.count(ProtDecl))
842 PotentialImplicitProtocols.push_back(ProtDecl);
844 if (PotentialImplicitProtocols.empty())
851 for (
unsigned i = 0, e = PotentialImplicitProtocols.size(); i != e; i++)
853 PotentialImplicitProtocols[i]))
854 ConformingProtocols.push_back(PotentialImplicitProtocols[i]);
856 if (ConformingProtocols.empty())
862 for (
unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
865 for (
unsigned i1 = 0, e1 = ConformingProtocols.size(); i1 != e1; i1++) {
867 if (PDecl == TargetPDecl)
876 MinimalConformingProtocols.push_back(TargetPDecl);
878 if (MinimalConformingProtocols.empty())
883 Editor->commit(commit);
886 void ObjCMigrateASTConsumer::CacheObjCNSIntegerTypedefed(
890 if (NSAPIObj->isObjCNSIntegerType(qt))
891 NSIntegerTypedefed = TypedefDcl;
892 else if (NSAPIObj->isObjCNSUIntegerType(qt))
893 NSUIntegerTypedefed = TypedefDcl;
896 bool ObjCMigrateASTConsumer::migrateNSEnumDecl(
ASTContext &Ctx,
903 if (NSIntegerTypedefed) {
904 TypedefDcl = NSIntegerTypedefed;
905 NSIntegerTypedefed =
nullptr;
907 else if (NSUIntegerTypedefed) {
908 TypedefDcl = NSUIntegerTypedefed;
909 NSUIntegerTypedefed =
nullptr;
913 FileID FileIdOfTypedefDcl =
917 if (FileIdOfTypedefDcl != FileIdOfEnumDcl)
924 StringRef NSIntegerName = NSAPIObj->GetNSIntegralKind(qt);
926 if (NSIntegerName.empty()) {
929 if (EnumTy->getDecl() == EnumDcl) {
931 if (!InsertFoundation(Ctx, TypedefDcl->
getLocStart()))
935 Editor->commit(commit);
944 if (!InsertFoundation(Ctx, TypedefDcl->
getLocStart()))
948 commit, NSIntegerName, NSOptions);
949 Editor->commit(commit);
954 const ObjCMigrateASTConsumer &ASTC,
960 std::string ClassString;
962 TypeLoc TL = TSInfo->getTypeLoc();
964 ClassString =
"instancetype";
969 ClassString +=
" (instancetype)";
972 commit.
replace(R, ClassString);
973 ASTC.Editor->commit(commit);
980 std::string ClassString;
982 TypeLoc TL = TSInfo->getTypeLoc();
984 ClassString = IDecl->
getName();
991 ClassString += IDecl->
getName(); ClassString +=
"*)";
994 commit.
replace(R, ClassString);
995 ASTC.Editor->commit(commit);
998 void ObjCMigrateASTConsumer::migrateMethodInstanceType(
ASTContext &Ctx,
1004 std::string ClassName;
1005 switch (OIT_Family) {
1007 migrateFactoryMethod(Ctx, CDecl, OM);
1010 ClassName =
"NSArray";
1013 ClassName =
"NSDictionary";
1032 IDecl = CatDecl->getClassInterface();
1033 else if (
ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(CDecl))
1038 migrateFactoryMethod(Ctx, CDecl, OM);
1055 T = TD->getDecl()->getUnderlyingType();
1060 if (UPointeeT->isRecordType()) {
1079 const AvailabilityAttr *AA1 = dyn_cast<AvailabilityAttr>(At1);
1082 const AvailabilityAttr *AA2 = dyn_cast<AvailabilityAttr>(At2);
1084 VersionTuple Introduced1 = AA1->getIntroduced();
1085 VersionTuple Deprecated1 = AA1->getDeprecated();
1086 VersionTuple Obsoleted1 = AA1->getObsoleted();
1087 bool IsUnavailable1 = AA1->getUnavailable();
1088 VersionTuple Introduced2 = AA2->getIntroduced();
1089 VersionTuple Deprecated2 = AA2->getDeprecated();
1090 VersionTuple Obsoleted2 = AA2->getObsoleted();
1091 bool IsUnavailable2 = AA2->getUnavailable();
1095 IsUnavailable1 == IsUnavailable2);
1099 bool &AvailabilityArgsMatch) {
1101 for (
unsigned i = 0, e = Attrs1.size(); i != e; i++) {
1103 for (
unsigned j = 0, f = Attrs2.size(); j != f; j++) {
1107 if (Attrs1[i]->
getKind() == Attrs2[j]->getKind()) {
1108 if (AvailabilityArgsMatch)
1128 bool &AvailabilityArgsMatch) {
1133 AvailabilityArgsMatch =
true;
1137 if (match && (Attrs2.size() > Attrs1.size()))
1146 std::string NameString = Name;
1152 bool ObjCMigrateASTConsumer::migrateProperty(
ASTContext &Ctx,
1176 unsigned LengthOfPrefix = 0;
1177 if (!SetterMethod) {
1179 StringRef getterNameString = getterName->
getName();
1180 bool IsPrefix = getterNameString.startswith(
"is");
1185 if (IsPrefix || getterNameString.startswith(
"get")) {
1186 LengthOfPrefix = (IsPrefix ? 2 : 3);
1187 const char *CGetterName = getterNameString.data() + LengthOfPrefix;
1192 if (CGetterName[0] &&
isUppercase(CGetterName[0])) {
1193 getterName = &Ctx.
Idents.
get(CGetterName);
1206 bool AvailabilityArgsMatch;
1207 if (SetterMethod->isDeprecated() ||
1212 QualType SRT = SetterMethod->getReturnType();
1215 const ParmVarDecl *argDecl = *SetterMethod->param_begin();
1222 (ASTMigrateActions &
1224 (ASTMigrateActions &
1226 AvailabilityArgsMatch);
1227 Editor->commit(commit);
1236 (ASTMigrateActions &
1238 (ASTMigrateActions &
1241 Editor->commit(commit);
1247 void ObjCMigrateASTConsumer::migrateNsReturnsInnerPointer(
ASTContext &Ctx,
1251 OM->
hasAttr<ObjCReturnsInnerPointerAttr>())
1256 !NSAPIObj->isMacroDefined(
"NS_RETURNS_INNER_POINTER"))
1261 Editor->commit(commit);
1264 void ObjCMigrateASTConsumer::migratePropertyNsReturnsInnerPointer(
ASTContext &Ctx,
1269 !NSAPIObj->isMacroDefined(
"NS_RETURNS_INNER_POINTER"))
1273 Editor->commit(commit);
1276 void ObjCMigrateASTConsumer::migrateAllMethodInstaceType(
ASTContext &Ctx,
1282 for (
auto *Method : CDecl->
methods()) {
1285 migrateMethodInstanceType(Ctx, CDecl, Method);
1289 void ObjCMigrateASTConsumer::migrateFactoryMethod(
ASTContext &Ctx,
1303 IDecl = CatDecl->getClassInterface();
1304 else if (
ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(CDecl))
1310 std::string StringClassName = IDecl->
getName();
1311 StringRef LoweredClassName(StringClassName);
1312 std::string StringLoweredClassName = LoweredClassName.lower();
1313 LoweredClassName = StringLoweredClassName;
1320 std::string MethodName = MethodIdName->
getName();
1322 StringRef STRefMethodName(MethodName);
1324 if (STRefMethodName.startswith(
"standard"))
1325 len = strlen(
"standard");
1326 else if (STRefMethodName.startswith(
"shared"))
1327 len = strlen(
"shared");
1328 else if (STRefMethodName.startswith(
"default"))
1329 len = strlen(
"default");
1332 MethodName = STRefMethodName.substr(len);
1334 std::string MethodNameSubStr = MethodName.substr(0, 3);
1335 StringRef MethodNamePrefix(MethodNameSubStr);
1336 std::string StringLoweredMethodNamePrefix = MethodNamePrefix.lower();
1337 MethodNamePrefix = StringLoweredMethodNamePrefix;
1338 size_t Ix = LoweredClassName.rfind(MethodNamePrefix);
1339 if (Ix == StringRef::npos)
1341 std::string ClassNamePostfix = LoweredClassName.substr(Ix);
1342 StringRef LoweredMethodName(MethodName);
1343 std::string StringLoweredMethodName = LoweredMethodName.lower();
1344 LoweredMethodName = StringLoweredMethodName;
1345 if (!LoweredMethodName.startswith(ClassNamePostfix))
1358 Ty = TD->getDecl()->getUnderlyingType();
1384 void ObjCMigrateASTConsumer::AnnotateImplicitBridging(
ASTContext &Ctx) {
1385 if (CFFunctionIBCandidates.empty())
1387 if (!NSAPIObj->isMacroDefined(
"CF_IMPLICIT_BRIDGING_ENABLED")) {
1388 CFFunctionIBCandidates.clear();
1393 const Decl *FirstFD = CFFunctionIBCandidates[0];
1394 const Decl *LastFD =
1395 CFFunctionIBCandidates[CFFunctionIBCandidates.size()-1];
1396 const char *PragmaString =
"\nCF_IMPLICIT_BRIDGING_ENABLED\n\n";
1399 PragmaString =
"\n\nCF_IMPLICIT_BRIDGING_DISABLED\n";
1403 if (isa<FunctionDecl>(LastFD)) {
1413 Editor->commit(commit);
1415 CFFunctionIBCandidates.clear();
1418 void ObjCMigrateASTConsumer::migrateCFAnnotation(
ASTContext &Ctx,
const Decl *
Decl) {
1422 if (Decl->
hasAttr<CFAuditedTransferAttr>()) {
1423 assert(CFFunctionIBCandidates.empty() &&
1424 "Cannot have audited functions/methods inside user " 1425 "provided CF_IMPLICIT_BRIDGING_ENABLE");
1430 if (
const FunctionDecl *FuncDecl = dyn_cast<FunctionDecl>(Decl)) {
1431 CF_BRIDGING_KIND AuditKind = migrateAddFunctionAnnotation(Ctx, FuncDecl);
1432 if (AuditKind == CF_BRIDGING_ENABLE) {
1433 CFFunctionIBCandidates.push_back(Decl);
1437 else if (AuditKind == CF_BRIDGING_MAY_INCLUDE) {
1438 if (!CFFunctionIBCandidates.empty()) {
1439 CFFunctionIBCandidates.push_back(Decl);
1445 AnnotateImplicitBridging(Ctx);
1448 migrateAddMethodAnnotation(Ctx, cast<ObjCMethodDecl>(Decl));
1449 AnnotateImplicitBridging(Ctx);
1453 void ObjCMigrateASTConsumer::AddCFAnnotations(
ASTContext &Ctx,
1454 const CallEffects &CE,
1456 bool ResultAnnotated) {
1458 if (!ResultAnnotated) {
1459 RetEffect Ret = CE.getReturnValue();
1460 const char *AnnotationString =
nullptr;
1461 if (Ret.getObjKind() == RetEffect::CF) {
1462 if (Ret.isOwned() && NSAPIObj->isMacroDefined(
"CF_RETURNS_RETAINED"))
1463 AnnotationString =
" CF_RETURNS_RETAINED";
1464 else if (Ret.notOwned() &&
1465 NSAPIObj->isMacroDefined(
"CF_RETURNS_NOT_RETAINED"))
1466 AnnotationString =
" CF_RETURNS_NOT_RETAINED";
1469 if (Ret.isOwned() && NSAPIObj->isMacroDefined(
"NS_RETURNS_RETAINED"))
1470 AnnotationString =
" NS_RETURNS_RETAINED";
1473 if (AnnotationString) {
1476 Editor->commit(commit);
1482 pe = FuncDecl->
param_end(); pi != pe; ++pi, ++i) {
1486 NSAPIObj->isMacroDefined(
"CF_CONSUMED")) {
1489 Editor->commit(commit);
1492 NSAPIObj->isMacroDefined(
"NS_CONSUMED")) {
1495 Editor->commit(commit);
1500 ObjCMigrateASTConsumer::CF_BRIDGING_KIND
1501 ObjCMigrateASTConsumer::migrateAddFunctionAnnotation(
1505 return CF_BRIDGING_NONE;
1507 CallEffects CE = CallEffects::getEffect(FuncDecl);
1508 bool FuncIsReturnAnnotated = (FuncDecl->
hasAttr<CFReturnsRetainedAttr>() ||
1509 FuncDecl->
hasAttr<CFReturnsNotRetainedAttr>() ||
1510 FuncDecl->
hasAttr<NSReturnsRetainedAttr>() ||
1511 FuncDecl->
hasAttr<NSReturnsNotRetainedAttr>() ||
1512 FuncDecl->
hasAttr<NSReturnsAutoreleasedAttr>());
1515 if (FuncIsReturnAnnotated && FuncDecl->
getNumParams() == 0)
1516 return CF_BRIDGING_NONE;
1518 bool ReturnCFAudited =
false;
1519 if (!FuncIsReturnAnnotated) {
1520 RetEffect Ret = CE.getReturnValue();
1521 if (Ret.getObjKind() == RetEffect::CF &&
1522 (Ret.isOwned() || Ret.notOwned()))
1523 ReturnCFAudited =
true;
1525 return CF_BRIDGING_NONE;
1532 bool ArgCFAudited =
false;
1534 pe = FuncDecl->
param_end(); pi != pe; ++pi, ++i) {
1539 ArgCFAudited =
true;
1541 ArgCFAudited =
true;
1546 AddCFAnnotations(Ctx, CE, FuncDecl, FuncIsReturnAnnotated);
1547 return CF_BRIDGING_NONE;
1551 if (ReturnCFAudited || ArgCFAudited)
1552 return CF_BRIDGING_ENABLE;
1554 return CF_BRIDGING_MAY_INCLUDE;
1557 void ObjCMigrateASTConsumer::migrateARCSafeAnnotation(
ASTContext &Ctx,
1559 if (!isa<ObjCInterfaceDecl>(CDecl) || CDecl->
isDeprecated())
1563 for (
const auto *Method : CDecl->
methods())
1564 migrateCFAnnotation(Ctx, Method);
1567 void ObjCMigrateASTConsumer::AddCFAnnotations(
ASTContext &Ctx,
1568 const CallEffects &CE,
1570 bool ResultAnnotated) {
1572 if (!ResultAnnotated) {
1573 RetEffect Ret = CE.getReturnValue();
1574 const char *AnnotationString =
nullptr;
1575 if (Ret.getObjKind() == RetEffect::CF) {
1576 if (Ret.isOwned() && NSAPIObj->isMacroDefined(
"CF_RETURNS_RETAINED"))
1577 AnnotationString =
" CF_RETURNS_RETAINED";
1578 else if (Ret.notOwned() &&
1579 NSAPIObj->isMacroDefined(
"CF_RETURNS_NOT_RETAINED"))
1580 AnnotationString =
" CF_RETURNS_NOT_RETAINED";
1593 if (Ret.isOwned() && NSAPIObj->isMacroDefined(
"NS_RETURNS_RETAINED"))
1594 AnnotationString =
" NS_RETURNS_RETAINED";
1599 if (AnnotationString) {
1602 Editor->commit(commit);
1608 pe = MethodDecl->
param_end(); pi != pe; ++pi, ++i) {
1612 NSAPIObj->isMacroDefined(
"CF_CONSUMED")) {
1615 Editor->commit(commit);
1620 void ObjCMigrateASTConsumer::migrateAddMethodAnnotation(
1626 CallEffects CE = CallEffects::getEffect(MethodDecl);
1627 bool MethodIsReturnAnnotated = (MethodDecl->
hasAttr<CFReturnsRetainedAttr>() ||
1628 MethodDecl->
hasAttr<CFReturnsNotRetainedAttr>() ||
1629 MethodDecl->
hasAttr<NSReturnsRetainedAttr>() ||
1630 MethodDecl->
hasAttr<NSReturnsNotRetainedAttr>() ||
1631 MethodDecl->
hasAttr<NSReturnsAutoreleasedAttr>());
1634 !MethodDecl->
hasAttr<NSConsumesSelfAttr>() &&
1637 NSAPIObj->isMacroDefined(
"NS_CONSUMES_SELF")) {
1640 Editor->commit(commit);
1644 if (MethodIsReturnAnnotated &&
1648 if (!MethodIsReturnAnnotated) {
1649 RetEffect Ret = CE.getReturnValue();
1650 if ((Ret.getObjKind() == RetEffect::CF ||
1652 (Ret.isOwned() || Ret.notOwned())) {
1653 AddCFAnnotations(Ctx, CE, MethodDecl,
false);
1664 pe = MethodDecl->
param_end(); pi != pe; ++pi, ++i) {
1669 AddCFAnnotations(Ctx, CE, MethodDecl, MethodIsReturnAnnotated);
1678 bool shouldVisitTemplateInstantiations()
const {
return false; }
1679 bool shouldWalkTypesOfTypeLocs()
const {
return false; }
1692 return !SuperInitChecker().TraverseStmt(MD->
getBody());
1695 void ObjCMigrateASTConsumer::inferDesignatedInitializers(
1702 if (!NSAPIObj->isMacroDefined(
"NS_DESIGNATED_INITIALIZER"))
1706 if (MD->isDeprecated() ||
1707 MD->getMethodFamily() !=
OMF_init ||
1708 MD->isDesignatedInitializerForTheInterface())
1717 Editor->commit(commit);
1722 bool ObjCMigrateASTConsumer::InsertFoundation(
ASTContext &Ctx,
1724 if (FoundationIncluded)
1728 auto *nsEnumId = &Ctx.
Idents.
get(
"NS_ENUM");
1730 FoundationIncluded =
true;
1735 commit.
insert(Loc,
"#ifndef NS_ENUM\n@import Foundation;\n#endif\n");
1737 commit.
insert(Loc,
"#ifndef NS_ENUM\n#import <Foundation/Foundation.h>\n#endif\n");
1738 Editor->commit(commit);
1739 FoundationIncluded =
true;
1749 RewritesReceiver(
Rewriter &Rewrite) : Rewrite(Rewrite) { }
1761 llvm::raw_ostream &OS;
1765 : SourceMgr(SM), OS(OS) {
1768 ~JSONEditWriter()
override { OS <<
"]\n"; }
1771 struct EntryWriter {
1773 llvm::raw_ostream &OS;
1776 : SourceMgr(SM), OS(OS) {
1790 llvm::sys::fs::make_absolute(Path);
1791 OS <<
" \"file\": \"";
1792 OS.write_escaped(Path.str()) <<
"\",\n";
1793 OS <<
" \"offset\": " << Offset <<
",\n";
1798 std::pair<FileID, unsigned>
Begin =
1800 std::pair<FileID, unsigned>
End =
1802 assert(Begin.first == End.first);
1803 assert(Begin.second <= End.second);
1804 unsigned Length = End.second - Begin.second;
1806 OS <<
" \"remove\": " << Length <<
",\n";
1809 void writeText(StringRef
Text) {
1810 OS <<
" \"text\": \"";
1811 OS.write_escaped(Text) <<
"\",\n";
1816 EntryWriter Writer(SourceMgr, OS);
1817 Writer.writeLoc(Loc);
1818 Writer.writeText(Text);
1822 EntryWriter Writer(SourceMgr, OS);
1824 Writer.writeRemove(Range);
1825 Writer.writeText(Text);
1829 EntryWriter Writer(SourceMgr, OS);
1831 Writer.writeRemove(Range);
1837 void ObjCMigrateASTConsumer::HandleTranslationUnit(
ASTContext &Ctx) {
1845 if (FileId.
isValid() && FileId != FID) {
1847 AnnotateImplicitBridging(Ctx);
1851 if (canModify(CDecl))
1852 migrateObjCContainerDecl(Ctx, CDecl);
1854 if (canModify(CatDecl))
1855 migrateObjCContainerDecl(Ctx, CatDecl);
1858 ObjCProtocolDecls.insert(PDecl->getCanonicalDecl());
1859 if (canModify(PDecl))
1860 migrateObjCContainerDecl(Ctx, PDecl);
1863 dyn_cast<ObjCImplementationDecl>(*D)) {
1866 migrateProtocolConformance(Ctx, ImpDecl);
1868 else if (
const EnumDecl *ED = dyn_cast<EnumDecl>(*D)) {
1876 if (migrateNSEnumDecl(Ctx, ED, TD) && TD)
1880 migrateNSEnumDecl(Ctx, ED,
nullptr);
1882 else if (
const TypedefDecl *TD = dyn_cast<TypedefDecl>(*D)) {
1890 if (
const EnumDecl *ED = dyn_cast<EnumDecl>(*N)) {
1891 if (canModify(ED)) {
1893 if (
const TypedefDecl *TDF = dyn_cast<TypedefDecl>(*N)) {
1895 if (migrateNSEnumDecl(Ctx, ED, TDF)) {
1897 CacheObjCNSIntegerTypedefed(TD);
1901 if (migrateNSEnumDecl(Ctx, ED, TD)) {
1907 CacheObjCNSIntegerTypedefed(TD);
1909 else if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(*D)) {
1912 migrateCFAnnotation(Ctx, FD);
1916 bool CanModify = canModify(CDecl);
1920 migrateAllMethodInstaceType(Ctx, CDecl);
1924 migrateARCSafeAnnotation(Ctx, CDecl);
1928 ImplD = dyn_cast<ObjCImplementationDecl>(*D)) {
1931 inferDesignatedInitializers(Ctx, ImplD);
1935 AnnotateImplicitBridging(Ctx);
1940 llvm::raw_fd_ostream OS(MigrateDir, EC, llvm::sys::fs::F_None);
1949 Editor->applyRewrites(Writer);
1954 RewritesReceiver Rec(rewriter);
1955 Editor->applyRewrites(Rec);
1958 I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) {
1964 llvm::raw_svector_ostream vecOS(newText);
1966 std::unique_ptr<llvm::MemoryBuffer> memBuf(
1967 llvm::MemoryBuffer::getMemBufferCopy(
1968 StringRef(newText.data(), newText.size()), file->
getName()));
1971 Remapper.
remap(filePath.str(), std::move(memBuf));
1987 using namespace llvm::sys::fs;
1988 using namespace llvm::sys::path;
1990 std::vector<std::string> Filenames;
1991 if (DirPath.empty() || !is_directory(DirPath))
1995 directory_iterator DI = directory_iterator(DirPath, EC);
1996 directory_iterator DE;
1997 for (; !EC && DI != DE; DI = DI.increment(EC)) {
1998 if (is_regular_file(DI->path()))
1999 Filenames.push_back(filename(DI->path()));
2005 std::unique_ptr<ASTConsumer>
2010 unsigned ObjCMTOpts = ObjCMTAction;
2021 std::vector<std::string> WhiteList =
2023 return llvm::make_unique<ObjCMigrateASTConsumer>(
2036 EditEntry() : File(),
Offset(), RemoveLen() {}
2044 Entry.Offset = unsigned(-1);
2049 Entry.Offset = unsigned(-2);
2053 llvm::FoldingSetNodeID
ID;
2054 ID.AddPointer(Val.File);
2055 ID.AddInteger(Val.Offset);
2056 ID.AddInteger(Val.RemoveLen);
2057 ID.AddString(Val.Text);
2058 return ID.ComputeHash();
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") {
2146 Entries.push_back(Entry);
2168 I = Edits.begin(), E = Edits.end(); I != E; ++I) {
2169 const EditEntry &Entry = *I;
2170 assert(Entry.File == FE);
2174 if (Entry.RemoveLen != 0) {
2181 commit.insert(Loc, Entry.Text);
2182 }
else if (Entry.Text.empty()) {
2183 commit.remove(Range);
2185 commit.replace(Range, Entry.Text);
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 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<const FileEntry *, 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(I->first->getName(), TempFile);
2268 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)
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.
Enable migration to modern ObjC readonly property.
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)
Enable migration to add conforming protocols.
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.
QualType getQualifiedType(SplitQualType split) const
Un-split a SplitQualType.
Decl - This represents one declaration (or definition), e.g.
The argument has its reference count decreased 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 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)
SourceLocation getLocEnd() const LLVM_READONLY
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.
Enable inferring NS_DESIGNATED_INITIALIZER for ObjC methods.
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.
SourceLocation getLocStart() const LLVM_READONLY
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.
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.
Expr * IgnoreImpCasts() LLVM_READONLY
IgnoreImpCasts - Skip past any implicit casts which might surround this expression.
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)
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.
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 literals.
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.
static Selector constructSetterSelector(IdentifierTable &Idents, SelectorTable &SelTable, const IdentifierInfo *Name)
Return the default setter selector for the given identifier.
Enable annotation of ObjCMethods of all kinds.
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()
Enable migration to modern ObjC readwrite property.
static bool UseNSOptionsMacro(Preprocessor &PP, ASTContext &Ctx, const EnumDecl *EnumDcl)
The argument has its reference count increased by 1.
static bool rewriteToNSEnumDecl(const EnumDecl *EnumDcl, const TypedefDecl *TypedefDcl, const NSAPI &NS, edit::Commit &commit, StringRef NSIntegerName, bool NSOptions)
SourceLocation getLocEnd() 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".
annotate property with NS_RETURNS_INNER_POINTER
Enable migration to NS_ENUM/NS_OPTIONS macros.
Expr * IgnoreParenCasts() LLVM_READONLY
IgnoreParenCasts - Ignore parentheses and casts.
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
static EditEntry getEmptyKey()
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).
ArgEffect
An ArgEffect summarizes the retain count behavior on an argument or receiver to a function or method...
SourceLocation getLocStart() const LLVM_READONLY
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...
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.
Expr - This represents one expression.
Enable migration to modern ObjC subscripting.
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
getAsIdentifierInfo - Retrieve the IdentifierInfo * stored in this declaration name, or NULL if this declaration name isn't a simple identifier.
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.
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.
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)
SourceLocation getLocStart() const LLVM_READONLY
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...
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)
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...
SourceLocation getLocStart() const LLVM_READONLY
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.
static bool AvailabilityAttrsMatch(Attr *At1, Attr *At2)
AvailabilityAttrsMatch - This routine checks that if comparing two availability attributes, all their components match.
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.
SourceLocation getLocEnd() const LLVM_READONLY
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
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...
Enable migration of ObjC methods to 'instancetype'.
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.
prefer 'atomic' property over 'nonatomic'.
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 converting setter/getter expressions to property-dot syntx.
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...
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.
bool isPointerType() const
The argument has its reference count decreased by 1.
use NS_NONATOMIC_IOSONLY for property 'atomic' attribute
A trivial tuple used to represent a source range.
ObjCMethodDecl * getMethod(Selector Sel, bool isInstance, bool AllowHidden=false) const
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.