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);
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()) {
748 if (EndOfEnumDclLoc.
isValid()) {
763 bool IsNSIntegerType) {
765 assert(!DesignatedEnumType.
isNull()
766 &&
"rewriteToNSMacroDecl - underlying enum type is null");
769 std::string TypeString = DesignatedEnumType.
getAsString(Policy);
770 std::string ClassString = IsNSIntegerType ?
"NS_ENUM(" :
"NS_OPTIONS(";
771 ClassString += TypeString;
781 commit.
replace(R, ClassString);
792 bool PowerOfTwo =
true;
793 bool AllHexdecimalEnumerator =
true;
794 uint64_t MaxPowerOfTwoVal = 0;
796 const Expr *InitExpr = Enumerator->getInitExpr();
799 AllHexdecimalEnumerator =
false;
803 if (
const BinaryOperator *BO = dyn_cast<BinaryOperator>(InitExpr))
804 if (BO->isShiftOp() || BO->isBitwiseOp())
807 uint64_t EnumVal = Enumerator->getInitVal().getZExtValue();
808 if (PowerOfTwo && EnumVal) {
809 if (!llvm::isPowerOf2_64(EnumVal))
811 else if (EnumVal > MaxPowerOfTwoVal)
812 MaxPowerOfTwoVal = EnumVal;
814 if (AllHexdecimalEnumerator && EnumVal) {
815 bool FoundHexdecimalEnumerator =
false;
821 FoundHexdecimalEnumerator =
822 (StringLit[0] ==
'0' && (
toLowercase(StringLit[1]) ==
'x'));
824 if (!FoundHexdecimalEnumerator)
825 AllHexdecimalEnumerator =
false;
828 return AllHexdecimalEnumerator || (PowerOfTwo && (MaxPowerOfTwoVal > 2));
831 void ObjCMigrateASTConsumer::migrateProtocolConformance(
ASTContext &Ctx,
834 if (!IDecl || ObjCProtocolDecls.empty() || IDecl->
isDeprecated())
838 llvm::SmallPtrSet<ObjCProtocolDecl *, 8> ExplicitProtocols;
843 if (!ExplicitProtocols.count(ProtDecl))
844 PotentialImplicitProtocols.push_back(ProtDecl);
846 if (PotentialImplicitProtocols.empty())
853 for (
unsigned i = 0, e = PotentialImplicitProtocols.size(); i != e; i++)
855 PotentialImplicitProtocols[i]))
856 ConformingProtocols.push_back(PotentialImplicitProtocols[i]);
858 if (ConformingProtocols.empty())
864 for (
unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
867 for (
unsigned i1 = 0, e1 = ConformingProtocols.size(); i1 != e1; i1++) {
869 if (PDecl == TargetPDecl)
878 MinimalConformingProtocols.push_back(TargetPDecl);
880 if (MinimalConformingProtocols.empty())
885 Editor->commit(commit);
888 void ObjCMigrateASTConsumer::CacheObjCNSIntegerTypedefed(
892 if (NSAPIObj->isObjCNSIntegerType(qt))
893 NSIntegerTypedefed = TypedefDcl;
894 else if (NSAPIObj->isObjCNSUIntegerType(qt))
895 NSUIntegerTypedefed = TypedefDcl;
898 bool ObjCMigrateASTConsumer::migrateNSEnumDecl(
ASTContext &Ctx,
905 if (NSIntegerTypedefed) {
906 TypedefDcl = NSIntegerTypedefed;
907 NSIntegerTypedefed =
nullptr;
909 else if (NSUIntegerTypedefed) {
910 TypedefDcl = NSUIntegerTypedefed;
911 NSUIntegerTypedefed =
nullptr;
915 FileID FileIdOfTypedefDcl =
919 if (FileIdOfTypedefDcl != FileIdOfEnumDcl)
926 StringRef NSIntegerName = NSAPIObj->GetNSIntegralKind(qt);
928 if (NSIntegerName.empty()) {
931 if (EnumTy->getDecl() == EnumDcl) {
933 if (!InsertFoundation(Ctx, TypedefDcl->
getBeginLoc()))
937 Editor->commit(commit);
946 if (!InsertFoundation(Ctx, TypedefDcl->
getBeginLoc()))
950 commit, NSIntegerName, NSOptions);
951 Editor->commit(commit);
956 const ObjCMigrateASTConsumer &ASTC,
962 std::string ClassString;
964 TypeLoc TL = TSInfo->getTypeLoc();
966 ClassString =
"instancetype";
971 ClassString +=
" (instancetype)";
974 commit.
replace(R, ClassString);
975 ASTC.Editor->commit(commit);
982 std::string ClassString;
984 TypeLoc TL = TSInfo->getTypeLoc();
986 ClassString = IDecl->
getName();
993 ClassString += IDecl->
getName(); ClassString +=
"*)";
996 commit.
replace(R, ClassString);
997 ASTC.Editor->commit(commit);
1000 void ObjCMigrateASTConsumer::migrateMethodInstanceType(
ASTContext &Ctx,
1006 std::string ClassName;
1007 switch (OIT_Family) {
1009 migrateFactoryMethod(Ctx, CDecl, OM);
1012 ClassName =
"NSArray";
1015 ClassName =
"NSDictionary";
1034 IDecl = CatDecl->getClassInterface();
1035 else if (
ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(CDecl))
1040 migrateFactoryMethod(Ctx, CDecl, OM);
1057 T = TD->getDecl()->getUnderlyingType();
1062 if (UPointeeT->isRecordType()) {
1081 const AvailabilityAttr *AA1 = dyn_cast<AvailabilityAttr>(At1);
1084 const AvailabilityAttr *AA2 = dyn_cast<AvailabilityAttr>(At2);
1086 VersionTuple Introduced1 = AA1->getIntroduced();
1087 VersionTuple Deprecated1 = AA1->getDeprecated();
1088 VersionTuple Obsoleted1 = AA1->getObsoleted();
1089 bool IsUnavailable1 = AA1->getUnavailable();
1090 VersionTuple Introduced2 = AA2->getIntroduced();
1091 VersionTuple Deprecated2 = AA2->getDeprecated();
1092 VersionTuple Obsoleted2 = AA2->getObsoleted();
1093 bool IsUnavailable2 = AA2->getUnavailable();
1097 IsUnavailable1 == IsUnavailable2);
1101 bool &AvailabilityArgsMatch) {
1103 for (
unsigned i = 0, e = Attrs1.size(); i != e; i++) {
1105 for (
unsigned j = 0, f = Attrs2.size(); j != f; j++) {
1109 if (Attrs1[i]->
getKind() == Attrs2[j]->getKind()) {
1110 if (AvailabilityArgsMatch)
1130 bool &AvailabilityArgsMatch) {
1135 AvailabilityArgsMatch =
true;
1139 if (match && (Attrs2.size() > Attrs1.size()))
1148 std::string NameString = Name;
1154 bool ObjCMigrateASTConsumer::migrateProperty(
ASTContext &Ctx,
1178 unsigned LengthOfPrefix = 0;
1179 if (!SetterMethod) {
1181 StringRef getterNameString = getterName->
getName();
1182 bool IsPrefix = getterNameString.startswith(
"is");
1187 if (IsPrefix || getterNameString.startswith(
"get")) {
1188 LengthOfPrefix = (IsPrefix ? 2 : 3);
1189 const char *CGetterName = getterNameString.data() + LengthOfPrefix;
1194 if (CGetterName[0] &&
isUppercase(CGetterName[0])) {
1195 getterName = &Ctx.
Idents.
get(CGetterName);
1208 bool AvailabilityArgsMatch;
1209 if (SetterMethod->isDeprecated() ||
1214 QualType SRT = SetterMethod->getReturnType();
1217 const ParmVarDecl *argDecl = *SetterMethod->param_begin();
1224 (ASTMigrateActions &
1226 (ASTMigrateActions &
1228 AvailabilityArgsMatch);
1229 Editor->commit(commit);
1238 (ASTMigrateActions &
1240 (ASTMigrateActions &
1243 Editor->commit(commit);
1249 void ObjCMigrateASTConsumer::migrateNsReturnsInnerPointer(
ASTContext &Ctx,
1253 OM->
hasAttr<ObjCReturnsInnerPointerAttr>())
1258 !NSAPIObj->isMacroDefined(
"NS_RETURNS_INNER_POINTER"))
1263 Editor->commit(commit);
1266 void ObjCMigrateASTConsumer::migratePropertyNsReturnsInnerPointer(
ASTContext &Ctx,
1271 !NSAPIObj->isMacroDefined(
"NS_RETURNS_INNER_POINTER"))
1275 Editor->commit(commit);
1278 void ObjCMigrateASTConsumer::migrateAllMethodInstaceType(
ASTContext &Ctx,
1284 for (
auto *Method : CDecl->
methods()) {
1287 migrateMethodInstanceType(Ctx, CDecl, Method);
1291 void ObjCMigrateASTConsumer::migrateFactoryMethod(
ASTContext &Ctx,
1305 IDecl = CatDecl->getClassInterface();
1306 else if (
ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(CDecl))
1312 std::string StringClassName = IDecl->
getName();
1313 StringRef LoweredClassName(StringClassName);
1314 std::string StringLoweredClassName = LoweredClassName.lower();
1315 LoweredClassName = StringLoweredClassName;
1322 std::string MethodName = MethodIdName->
getName();
1324 StringRef STRefMethodName(MethodName);
1326 if (STRefMethodName.startswith(
"standard"))
1327 len = strlen(
"standard");
1328 else if (STRefMethodName.startswith(
"shared"))
1329 len = strlen(
"shared");
1330 else if (STRefMethodName.startswith(
"default"))
1331 len = strlen(
"default");
1334 MethodName = STRefMethodName.substr(len);
1336 std::string MethodNameSubStr = MethodName.substr(0, 3);
1337 StringRef MethodNamePrefix(MethodNameSubStr);
1338 std::string StringLoweredMethodNamePrefix = MethodNamePrefix.lower();
1339 MethodNamePrefix = StringLoweredMethodNamePrefix;
1340 size_t Ix = LoweredClassName.rfind(MethodNamePrefix);
1341 if (Ix == StringRef::npos)
1343 std::string ClassNamePostfix = LoweredClassName.substr(Ix);
1344 StringRef LoweredMethodName(MethodName);
1345 std::string StringLoweredMethodName = LoweredMethodName.lower();
1346 LoweredMethodName = StringLoweredMethodName;
1347 if (!LoweredMethodName.startswith(ClassNamePostfix))
1360 Ty = TD->getDecl()->getUnderlyingType();
1386 void ObjCMigrateASTConsumer::AnnotateImplicitBridging(
ASTContext &Ctx) {
1387 if (CFFunctionIBCandidates.empty())
1389 if (!NSAPIObj->isMacroDefined(
"CF_IMPLICIT_BRIDGING_ENABLED")) {
1390 CFFunctionIBCandidates.clear();
1395 const Decl *FirstFD = CFFunctionIBCandidates[0];
1396 const Decl *LastFD =
1397 CFFunctionIBCandidates[CFFunctionIBCandidates.size()-1];
1398 const char *PragmaString =
"\nCF_IMPLICIT_BRIDGING_ENABLED\n\n";
1401 PragmaString =
"\n\nCF_IMPLICIT_BRIDGING_DISABLED\n";
1405 if (isa<FunctionDecl>(LastFD)) {
1415 Editor->commit(commit);
1417 CFFunctionIBCandidates.clear();
1420 void ObjCMigrateASTConsumer::migrateCFAnnotation(
ASTContext &Ctx,
const Decl *
Decl) {
1424 if (Decl->
hasAttr<CFAuditedTransferAttr>()) {
1425 assert(CFFunctionIBCandidates.empty() &&
1426 "Cannot have audited functions/methods inside user " 1427 "provided CF_IMPLICIT_BRIDGING_ENABLE");
1432 if (
const FunctionDecl *FuncDecl = dyn_cast<FunctionDecl>(Decl)) {
1433 CF_BRIDGING_KIND AuditKind = migrateAddFunctionAnnotation(Ctx, FuncDecl);
1434 if (AuditKind == CF_BRIDGING_ENABLE) {
1435 CFFunctionIBCandidates.push_back(Decl);
1439 else if (AuditKind == CF_BRIDGING_MAY_INCLUDE) {
1440 if (!CFFunctionIBCandidates.empty()) {
1441 CFFunctionIBCandidates.push_back(Decl);
1447 AnnotateImplicitBridging(Ctx);
1450 migrateAddMethodAnnotation(Ctx, cast<ObjCMethodDecl>(Decl));
1451 AnnotateImplicitBridging(Ctx);
1455 void ObjCMigrateASTConsumer::AddCFAnnotations(
ASTContext &Ctx,
1458 bool ResultAnnotated) {
1460 if (!ResultAnnotated) {
1462 const char *AnnotationString =
nullptr;
1464 if (Ret.
isOwned() && NSAPIObj->isMacroDefined(
"CF_RETURNS_RETAINED"))
1465 AnnotationString =
" CF_RETURNS_RETAINED";
1467 NSAPIObj->isMacroDefined(
"CF_RETURNS_NOT_RETAINED"))
1468 AnnotationString =
" CF_RETURNS_NOT_RETAINED";
1471 if (Ret.
isOwned() && NSAPIObj->isMacroDefined(
"NS_RETURNS_RETAINED"))
1472 AnnotationString =
" NS_RETURNS_RETAINED";
1475 if (AnnotationString) {
1478 Editor->commit(commit);
1484 pe = FuncDecl->
param_end(); pi != pe; ++pi, ++i) {
1488 !pd->
hasAttr<CFConsumedAttr>() &&
1489 NSAPIObj->isMacroDefined(
"CF_CONSUMED")) {
1492 Editor->commit(commit);
1494 !pd->
hasAttr<NSConsumedAttr>() &&
1495 NSAPIObj->isMacroDefined(
"NS_CONSUMED")) {
1498 Editor->commit(commit);
1503 ObjCMigrateASTConsumer::CF_BRIDGING_KIND
1504 ObjCMigrateASTConsumer::migrateAddFunctionAnnotation(
1508 return CF_BRIDGING_NONE;
1510 CallEffects CE = CallEffects::getEffect(FuncDecl);
1511 bool FuncIsReturnAnnotated = (FuncDecl->
hasAttr<CFReturnsRetainedAttr>() ||
1512 FuncDecl->
hasAttr<CFReturnsNotRetainedAttr>() ||
1513 FuncDecl->
hasAttr<NSReturnsRetainedAttr>() ||
1514 FuncDecl->
hasAttr<NSReturnsNotRetainedAttr>() ||
1515 FuncDecl->
hasAttr<NSReturnsAutoreleasedAttr>());
1518 if (FuncIsReturnAnnotated && FuncDecl->
getNumParams() == 0)
1519 return CF_BRIDGING_NONE;
1521 bool ReturnCFAudited =
false;
1522 if (!FuncIsReturnAnnotated) {
1526 ReturnCFAudited =
true;
1528 return CF_BRIDGING_NONE;
1535 bool ArgCFAudited =
false;
1537 pe = FuncDecl->
param_end(); pi != pe; ++pi, ++i) {
1543 ArgCFAudited =
true;
1545 ArgCFAudited =
true;
1549 AddCFAnnotations(Ctx, CE, FuncDecl, FuncIsReturnAnnotated);
1550 return CF_BRIDGING_NONE;
1554 if (ReturnCFAudited || ArgCFAudited)
1555 return CF_BRIDGING_ENABLE;
1557 return CF_BRIDGING_MAY_INCLUDE;
1560 void ObjCMigrateASTConsumer::migrateARCSafeAnnotation(
ASTContext &Ctx,
1562 if (!isa<ObjCInterfaceDecl>(CDecl) || CDecl->
isDeprecated())
1566 for (
const auto *Method : CDecl->
methods())
1567 migrateCFAnnotation(Ctx, Method);
1570 void ObjCMigrateASTConsumer::AddCFAnnotations(
ASTContext &Ctx,
1573 bool ResultAnnotated) {
1575 if (!ResultAnnotated) {
1577 const char *AnnotationString =
nullptr;
1579 if (Ret.
isOwned() && NSAPIObj->isMacroDefined(
"CF_RETURNS_RETAINED"))
1580 AnnotationString =
" CF_RETURNS_RETAINED";
1582 NSAPIObj->isMacroDefined(
"CF_RETURNS_NOT_RETAINED"))
1583 AnnotationString =
" CF_RETURNS_NOT_RETAINED";
1596 if (Ret.
isOwned() && NSAPIObj->isMacroDefined(
"NS_RETURNS_RETAINED"))
1597 AnnotationString =
" NS_RETURNS_RETAINED";
1602 if (AnnotationString) {
1605 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 CallEffects CE = CallEffects::getEffect(MethodDecl);
1632 bool MethodIsReturnAnnotated =
1633 (MethodDecl->
hasAttr<CFReturnsRetainedAttr>() ||
1634 MethodDecl->
hasAttr<CFReturnsNotRetainedAttr>() ||
1635 MethodDecl->
hasAttr<NSReturnsRetainedAttr>() ||
1636 MethodDecl->
hasAttr<NSReturnsNotRetainedAttr>() ||
1637 MethodDecl->
hasAttr<NSReturnsAutoreleasedAttr>());
1640 !MethodDecl->
hasAttr<NSConsumesSelfAttr>() &&
1643 NSAPIObj->isMacroDefined(
"NS_CONSUMES_SELF")) {
1646 Editor->commit(commit);
1650 if (MethodIsReturnAnnotated &&
1654 if (!MethodIsReturnAnnotated) {
1659 AddCFAnnotations(Ctx, CE, MethodDecl,
false);
1670 pe = MethodDecl->
param_end(); pi != pe; ++pi, ++i) {
1675 AddCFAnnotations(Ctx, CE, 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)
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;
1755 RewritesReceiver(
Rewriter &Rewrite) : Rewrite(Rewrite) { }
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";
1804 std::pair<FileID, unsigned>
Begin =
1806 std::pair<FileID, unsigned>
End =
1808 assert(Begin.first == End.first);
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);
1830 Writer.writeRemove(Range);
1831 Writer.writeText(Text);
1835 EntryWriter Writer(SourceMgr, OS);
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);
1864 ObjCProtocolDecls.insert(PDecl->getCanonicalDecl());
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)) {
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::F_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(filename(DI->path()));
2011 std::unique_ptr<ASTConsumer>
2016 unsigned ObjCMTOpts = ObjCMTAction;
2027 std::vector<std::string> WhiteList =
2029 return llvm::make_unique<ObjCMigrateASTConsumer>(
2042 EditEntry() : File(),
Offset(), RemoveLen() {}
2050 Entry.Offset = unsigned(-1);
2055 Entry.Offset = unsigned(-2);
2059 llvm::FoldingSetNodeID
ID;
2060 ID.AddPointer(Val.File);
2061 ID.AddInteger(Val.Offset);
2062 ID.AddInteger(Val.RemoveLen);
2063 ID.AddString(Val.Text);
2064 return ID.ComputeHash();
2066 static bool isEqual(
const EditEntry &LHS,
const EditEntry &RHS) {
2067 return LHS.File == RHS.File &&
2068 LHS.Offset == RHS.Offset &&
2069 LHS.RemoveLen == RHS.RemoveLen &&
2070 LHS.Text == RHS.Text;
2076 class RemapFileParser {
2080 RemapFileParser(
FileManager &FileMgr) : FileMgr(FileMgr) { }
2085 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
2086 llvm::MemoryBuffer::getFile(File);
2091 Stream YAMLStream(FileBufOrErr.get()->getMemBufferRef(),
SM);
2092 document_iterator I = YAMLStream.begin();
2093 if (I == YAMLStream.end())
2095 Node *Root = I->getRoot();
2099 SequenceNode *SeqNode = dyn_cast<SequenceNode>(Root);
2103 for (SequenceNode::iterator
2104 AI = SeqNode->begin(), AE = SeqNode->end(); AI != AE; ++AI) {
2105 MappingNode *MapNode = dyn_cast<MappingNode>(&*AI);
2108 parseEdit(MapNode, Entries);
2115 void parseEdit(llvm::yaml::MappingNode *
Node,
2119 bool Ignore =
false;
2121 for (MappingNode::iterator
2122 KVI = Node->begin(), KVE = Node->end(); KVI != KVE; ++KVI) {
2123 ScalarNode *KeyString = dyn_cast<ScalarNode>((*KVI).getKey());
2127 StringRef Key = KeyString->getValue(KeyStorage);
2129 ScalarNode *ValueString = dyn_cast<ScalarNode>((*KVI).getValue());
2133 StringRef Val = ValueString->getValue(ValueStorage);
2135 if (Key ==
"file") {
2140 }
else if (Key ==
"offset") {
2141 if (Val.getAsInteger(10, Entry.Offset))
2143 }
else if (Key ==
"remove") {
2144 if (Val.getAsInteger(10, Entry.RemoveLen))
2146 }
else if (Key ==
"text") {
2152 Entries.push_back(Entry);
2174 I = Edits.begin(), E = Edits.end(); I != E; ++I) {
2175 const EditEntry &Entry = *I;
2176 assert(Entry.File == FE);
2180 if (Entry.RemoveLen != 0) {
2187 commit.insert(Loc, Entry.Text);
2188 }
else if (Entry.Text.empty()) {
2189 commit.remove(Range);
2191 commit.replace(Range, Entry.Text);
2197 RewritesReceiver Rec(rewriter);
2202 llvm::raw_svector_ostream
OS(NewText);
2207 if (fs::createTemporaryFile(path::filename(FE->
getName()),
2208 path::extension(FE->
getName()).drop_front(), FD,
2211 return std::string();
2214 llvm::raw_fd_ostream TmpOut(FD,
true);
2215 TmpOut.write(NewText.data(), NewText.size());
2218 return TempPath.str();
2222 std::vector<std::pair<std::string,std::string> > &remap,
2225 bool hasErrorOccurred =
false;
2229 RemapFileParser
Parser(FileMgr);
2234 DiagClient,
false));
2236 typedef llvm::DenseMap<const FileEntry *, std::vector<EditEntry> >
2238 FileEditEntriesTy FileEditEntries;
2243 I = remapFiles.begin(), E = remapFiles.end(); I != E; ++I) {
2245 if (Parser.parse(*I, Entries))
2249 EI = Entries.begin(), EE = Entries.end(); EI != EE; ++EI) {
2250 EditEntry &Entry = *EI;
2253 std::pair<llvm::DenseSet<EditEntry>::iterator,
bool>
2254 Insert = EntriesSet.insert(Entry);
2258 FileEditEntries[Entry.File].push_back(Entry);
2262 for (FileEditEntriesTy::iterator
2263 I = FileEditEntries.begin(), E = FileEditEntries.end(); I != E; ++I) {
2266 if (TempFile.empty()) {
2267 hasErrorOccurred =
true;
2271 remap.emplace_back(I->first->getName(), TempFile);
2274 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)
Encapsulates the retain count semantics on the arguments, return value, and receiver (if any) of a fu...
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override
Create the AST consumer object for this action, if supported.
static bool AttributesMatch(const Decl *Decl1, const Decl *Decl2, bool &AvailabilityArgsMatch)
AttributesMatch - This routine checks list of attributes for two decls.
Represents a function declaration or definition.
static bool MatchTwoAttributeLists(const AttrVec &Attrs1, const AttrVec &Attrs2, bool &AvailabilityArgsMatch)
Enable migration to modern ObjC readwrite property.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
The receiver is an object instance.
SourceLocation getLocWithOffset(int Offset) const
Return a source location with the specified offset from this SourceLocation.
std::string ObjCMTWhiteListPath
Smart pointer class that efficiently represents Objective-C method names.
SelectorTable & getSelectorTable()
PointerType - C99 6.7.5.1 - Pointer Declarators.
QualType getPointeeType() const
A (possibly-)qualified type.
bool isBlockPointerType() const
unsigned param_size() const
bool rewriteToObjCSubscriptSyntax(const ObjCMessageExpr *Msg, const NSAPI &NS, Commit &commit)
Implements support for file system lookup, file system caching, and directory search management...
ObjCInterfaceDecl * getClassInterface()
ASTConsumer - This is an abstract interface that should be implemented by clients that read ASTs...
Enable migration to modern ObjC readonly property.
Defines the clang::FileManager interface and associated types.
bool rewriteToObjCLiteralSyntax(const ObjCMessageExpr *Msg, const NSAPI &NS, Commit &commit, const ParentMap *PMap)
static bool hasSuperInitCall(const ObjCMethodDecl *MD)
SourceRange getBraceRange() const
DominatorTree GraphTraits specialization so the DominatorTree can be iterable by generic graph iterat...
Stmt - This represents one statement.
bool insertWrap(StringRef before, CharSourceRange range, StringRef after)
SourceLocation getSuperClassLoc() const
Retrieve the starting location of the superclass.
Represents the declaration of a typedef-name via the 'typedef' type specifier.
use NS_NONATOMIC_IOSONLY for property 'atomic' attribute
ObjKind getObjKind() const
QualType getQualifiedType(SplitQualType split) const
Un-split a SplitQualType.
Decl - This represents one declaration (or definition), e.g.
SourceLocation getBeginLoc() const LLVM_READONLY
The argument has its reference count increased by 1.
const char * getCharacterData(SourceLocation SL, bool *Invalid=nullptr) const
Return a pointer to the start of the specified location in the appropriate spelling MemoryBuffer...
static bool TypeIsInnerPointer(QualType T)
ObjCProtocolDecl * lookupNestedProtocol(IdentifierInfo *Name)
DiagnosticsEngine & getDiagnostics() const
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
bool insertAfterToken(SourceLocation loc, StringRef text, bool beforePreviousInsertions=false)
A Range represents the closed range [from, to].
SourceLocation getEndLoc() const LLVM_READONLY
A container of type source information.
Parser - This implements a parser for the C family of languages.
bool insertFromRange(SourceLocation loc, CharSourceRange range, bool afterToken=false, bool beforePreviousInsertions=false)
ArrayRef< ParmVarDecl * >::const_iterator param_const_iterator
param_const_iterator param_end() const
SourceLocation getEndLoc() const
Get the end source location.
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
ArrayRef< ArgEffect > getArgs() const
Returns the argument effects for a call.
enumerator_range enumerators() const
void removeObjCLifetime()
QualType getReturnType() const
SourceLocation findSemiAfterLocation(SourceLocation loc, ASTContext &Ctx, bool IsDecl=false)
'Loc' is the end of a statement range.
static std::vector< std::string > getWhiteListFilenames(StringRef DirPath)
const T * getAs() const
Member-template getAs<specific type>'.
bool getRawToken(SourceLocation Loc, Token &Result, bool IgnoreWhiteSpace=false)
Relex the token at the specified location.
Abstract interface, implemented by clients of the front-end, which formats and prints fully processed...
ObjCMethodDecl - Represents an instance or class method declaration.
ObjKind getObjKind() const
RewriteBuffer - As code is rewritten, SourceBuffer's from the original input with modifications get a...
Describes how types, statements, expressions, and declarations should be printed. ...
Represents a parameter to a function.
bool isLiteral() const
Return true if this is a "literal", like a numeric constant, string, etc.
The collection of all-type qualifiers we support.
static EditEntry getTombstoneKey()
SourceLocation getDeclaratorEndLoc() const
Returns the location where the declarator ends.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Base wrapper for a particular "section" of type source info.
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)
Enable migration to modern ObjC literals.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
The results of name lookup within a DeclContext.
const ParmVarDecl *const * param_const_iterator
ObjCMethodFamily
A family of Objective-C methods.
FullExpr - Represents a "full-expression" node.
SourceLocation getBeginLoc() const LLVM_READONLY
bool isObjCIdType() const
instmeth_range instance_methods() const
method_range methods() const
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override
Create the AST consumer object for this action, if supported.
Token - This structure provides full information about a lexed token.
bool ReplaceText(SourceLocation Start, unsigned OrigLength, StringRef NewStr)
ReplaceText - This method replaces a range of characters in the input buffer with a new string...
SourceLocation findLocationAfterSemi(SourceLocation loc, ASTContext &Ctx, bool IsDecl=false)
'Loc' is the end of a statement range.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
unsigned SuppressStrongLifetime
When true, suppress printing of the __strong lifetime qualifier in ARC.
static void ReplaceWithInstancetype(ASTContext &Ctx, const ObjCMigrateASTConsumer &ASTC, ObjCMethodDecl *OM)
bool isDeprecated(std::string *Message=nullptr) const
Determine whether this declaration is marked 'deprecated'.
ObjCMethodFamily getMethodFamily() const
Determines the family of this method.
The argument has its reference count decreased by 1.
static Selector constructSetterSelector(IdentifierTable &Idents, SelectorTable &SelTable, const IdentifierInfo *Name)
Return the default setter selector for the given identifier.
bool replace(CharSourceRange range, StringRef text)
static const char * PropertyMemoryAttribute(ASTContext &Context, QualType ArgType)
ObjCContainerDecl - Represents a container for method declarations.
tok::TokenKind getTokenID() const
If this is a source-language token (e.g.
void remap(StringRef filePath, std::unique_ptr< llvm::MemoryBuffer > memBuf)
FrontendOptions & getFrontendOpts()
static bool UseNSOptionsMacro(Preprocessor &PP, ASTContext &Ctx, const EnumDecl *EnumDcl)
static bool rewriteToNSEnumDecl(const EnumDecl *EnumDcl, const TypedefDecl *TypedefDcl, const NSAPI &NS, edit::Commit &commit, StringRef NSIntegerName, bool NSOptions)
SourceLocation getBeginLoc() const LLVM_READONLY
Concrete class used by the front-end to report problems and issues.
bool BeginInvocation(CompilerInstance &CI) override
Callback before starting processing a single input, giving the opportunity to modify the CompilerInvo...
const clang::PrintingPolicy & getPrintingPolicy() const
A builtin binary operation expression such as "x + y" or "x <= y".
Expr * IgnoreParenCasts() LLVM_READONLY
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
Enable migration of ObjC methods to 'instancetype'.
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).
ObjCProtocolDecl * lookupProtocolNamed(IdentifierInfo *PName)
bool flushToFile(StringRef outputPath, DiagnosticsEngine &Diag)
static bool AuditedType(QualType AT)
AuditedType - This routine audits the type AT and returns false if it is one of known CF object types...
SourceLocation getEndLoc() const LLVM_READONLY
bool FixupRelativePath(SmallVectorImpl< char > &path) const
If path is not absolute and FileSystemOptions set the working directory, the path is modified to be r...
TypeSourceInfo * getTypeSourceInfo() const
bool ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl, const ObjCMethodDecl *MethodImp)
Enable migration to add conforming protocols.
LLVM_READONLY bool isIdentifierHead(unsigned char c, bool AllowDollar=false)
Returns true if this is a valid first character of a C identifier, which is [a-zA-Z_].
SourceLocation getBeginLoc() const
Get the begin source location.
This represents one expression.
Represents a character-granular source range.
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
FileID createFileID(const FileEntry *SourceFile, SourceLocation IncludePos, SrcMgr::CharacteristicKind FileCharacter, int LoadedID=0, unsigned LoadedOffset=0)
Create a new FileID that represents the specified file being #included from the specified IncludePosi...
bool isObjCBuiltinType() const
ASTContext & getASTContext() const
bool isObjCRetainableType() const
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
SourceLocation getSelectorStartLoc() const
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file. ...
Defines the clang::Preprocessor interface.
StringRef getNameForSlot(unsigned argIndex) const
Retrieve the name at a given position in the selector.
static bool IsCategoryNameWithDeprecatedSuffix(ObjCContainerDecl *D)
ObjCInterfaceDecl * getSuperClass() const
Expr ** getArgs()
Retrieve the arguments to this message, not including the receiver.
ObjCInstanceTypeFamily
A family of Objective-C methods.
IdentifierInfo * getAsIdentifierInfo() const
Retrieve the IdentifierInfo * stored in this declaration name, or null if this declaration name isn't...
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
protocol_loc_iterator protocol_loc_end() const
Enable annotation of ObjCMethods of all kinds.
static bool IsValidIdentifier(ASTContext &Ctx, const char *Name)
bool isCFObjectRef(QualType T)
An expression that sends a message to the given Objective-C object or class.
static bool subscriptOperatorNeedsParens(const Expr *FullExpr)
SourceLocation getEnd() const
bool isInstanceMethod() const
ReceiverKind getReceiverKind() const
Determine the kind of receiver that this message is being sent to.
int getRangeSize(SourceRange Range, RewriteOptions opts=RewriteOptions()) const
getRangeSize - Return the size in bytes of the specified range if they are in the same file...
void CollectInheritedProtocols(const Decl *CDecl, llvm::SmallPtrSet< ObjCProtocolDecl *, 8 > &Protocols)
CollectInheritedProtocols - Collect all protocols in current class and those inherited by it...
Selector getSelector() const
bool isNull() const
Return true if this QualType doesn't point to a type yet.
SourceLocation getEndLoc() const LLVM_READONLY
static CharSourceRange getCharRange(SourceRange R)
SourceManager & getSourceManager() const
TypeSourceInfo * getReturnTypeSourceInfo() const
RecordDecl * getDecl() const
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override
Create the AST consumer object for this action, if supported.
static void ReplaceWithClasstype(const ObjCMigrateASTConsumer &ASTC, ObjCMethodDecl *OM)
There is no lifetime qualification on this type.
unsigned getNumArgs() const
Return the number of actual arguments in this message, not counting the receiver. ...
LLVM_READONLY char toLowercase(char c)
Converts the given ASCII character to its lowercase equivalent.
Assigning into this object requires the old value to be released and the new value to be retained...
ArgEffectKind getKind() const
IdentifierInfo * getIdentifierInfoForSlot(unsigned argIndex) const
Retrieve the identifier at a given position in the selector.
static void append_attr(std::string &PropertyString, const char *attr, bool &LParenAdded)
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
Encodes a location in the source.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
raw_ostream & write(raw_ostream &Stream) const
Write to Stream the result of applying all changes to the original buffer.
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of enums...
StringRef getName() const
static bool rewriteToObjCInterfaceDecl(const ObjCInterfaceDecl *IDecl, llvm::SmallVectorImpl< ObjCProtocolDecl *> &ConformingProtocols, const NSAPI &NS, edit::Commit &commit)
decl_iterator decls_begin() const
static unsigned getHashValue(const EditEntry &Val)
prefer 'atomic' property over 'nonatomic'.
bool flushToDisk(StringRef outputDir, DiagnosticsEngine &Diag)
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
Options for controlling the compiler diagnostics engine.
static void MigrateBlockOrFunctionPointerTypeVariable(std::string &PropertyString, const std::string &TypeString, const char *name)
ObjCMethodFamily getMethodFamily() const
Records preprocessor conditional directive regions and allows querying in which region source locatio...
IdentifierTable & getIdentifierTable()
static bool ClassImplementsAllMethodsAndProperties(ASTContext &Ctx, const ObjCImplementationDecl *ImpDecl, const ObjCInterfaceDecl *IDecl, ObjCProtocolDecl *Protocol)
Cached information about one file (either on disk or in the virtual file system). ...
const RewriteBuffer * getRewriteBufferFor(FileID FID) const
getRewriteBufferFor - Return the rewrite buffer for the specified FileID.
Stmt * getBody() const override
Retrieve the body of this method, if it has one.
bool InsertText(SourceLocation Loc, StringRef Str, bool InsertAfter=true, bool indentNewLines=false)
InsertText - Insert the specified string at the specified location in the original buffer...
SourceLocation getSuperLoc() const
Retrieve the location of the 'super' keyword for a class or instance message to 'super', otherwise an invalid source location.
ObjCInterfaceDecl * lookupInheritedClass(const IdentifierInfo *ICName)
lookupInheritedClass - This method returns ObjCInterfaceDecl * of the super class whose name is passe...
ObjCCategoryDecl - Represents a category declaration.
Enable inferring NS_DESIGNATED_INITIALIZER for ObjC methods.
static bool AvailabilityAttrsMatch(Attr *At1, Attr *At2)
AvailabilityAttrsMatch - This routine checks that if comparing two availability attributes, all their components match.
annotate property with NS_RETURNS_INNER_POINTER
SourceLocation getSelectorLoc(unsigned Index) const
bool isObjCObjectPointerType() const
bool isAnyPointerType() const
MacroDefinition getMacroDefinitionAtLoc(const IdentifierInfo *II, SourceLocation Loc)
Enable converting setter/getter expressions to property-dot syntx.
Represents one property declaration in an Objective-C interface.
bool isImplicit() const
Indicates whether the message send was implicitly generated by the implementation.
unsigned getCustomDiagID(Level L, const char(&FormatString)[N])
Return an ID for a diagnostic with the specified format string and level.
const ObjCMethodDecl * getMethodDecl() const
static StringRef GetUnsignedName(StringRef NSIntegerName)
std::map< FileID, RewriteBuffer >::iterator buffer_iterator
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
QualType getObjCInstanceType()
Retrieve the Objective-C "instancetype" type, if already known; otherwise, returns a NULL type;...
StringRef getName() const
Return the actual identifier string.
void setIgnoreAllWarnings(bool Val)
When set to true, any unmapped warnings are ignored.
decl_iterator - Iterates through the declarations stored within this context.
Expr * getInstanceReceiver()
Returns the object expression (receiver) for an instance message, or null for a message that is not a...
ast_type_traits::DynTypedNode Node
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
const ObjCInterfaceDecl * getClassInterface() const
Dataflow Directional Tag Classes.
bool isValid() const
Return true if this is a valid SourceLocation object.
FileManager & getFileManager() const
Return the current file manager to the caller.
ObjCMigrateAction(std::unique_ptr< FrontendAction > WrappedAction, StringRef migrateDir, unsigned migrateAction)
bool isMacroDefined(StringRef Id) const
Returns true if Id is currently defined as a macro.
static void rewriteToNSMacroDecl(ASTContext &Ctx, const EnumDecl *EnumDcl, const TypedefDecl *TypedefDcl, const NSAPI &NS, edit::Commit &commit, bool IsNSIntegerType)
const ObjCProtocolList & getReferencedProtocols() const
Used for handling and querying diagnostic IDs.
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
SourceManager & getSourceManager() const
Return the current source manager.
bool hasObjCLifetime() const
Enable migration to modern ObjC subscripting.
unsigned getLength() const
param_iterator param_end()
A frontend action which simply wraps some other runtime-specified frontend action.
bool hasDesignatedInitializers() const
Returns true if this interface decl contains at least one initializer marked with the 'objc_designate...
Represents a pointer to an Objective C object.
static bool IsVoidStarType(QualType Ty)
const char * getLiteralData() const
getLiteralData - For a literal token (numeric constant, string, etc), this returns a pointer to the s...
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
ObjCImplementationDecl - Represents a class definition - this is where method definitions are specifi...
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Indicates that the tracking object is a descendant of a referenced-counted OSObject, used in the Darwin kernel.
bool hasBody() const override
Determine whether this method has a body.
bool commit(const Commit &commit)
static bool isEqual(const EditEntry &LHS, const EditEntry &RHS)
param_const_iterator param_begin() const
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
SourceLocation getEnd() const
bool getFileRemappingsFromFileList(std::vector< std::pair< std::string, std::string > > &remap, ArrayRef< StringRef > remapFiles, DiagnosticConsumer *DiagClient)
Get the set of file remappings from a list of files with remapping info.
SourceManager & getSourceManager()
Keeps track of options that affect how file operations are performed.
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
Preprocessor & getPreprocessor() const
Return the current preprocessor.
Reading or writing from this object requires a barrier call.
bool initFromDisk(StringRef outputDir, DiagnosticsEngine &Diag, bool ignoreIfFilesChanged)
void applyRewrites(EditsReceiver &receiver, bool adjustRemovals=true)
Rewriter - This is the main interface to the rewrite buffers.
const ObjCPropertyDecl * findPropertyDecl(bool CheckOverrides=true) const
Returns the property associated with this method's selector.
TranslationUnitDecl * getTranslationUnitDecl() const
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
ArgEffect getReceiver() const
Returns the effects on the receiver.
ObjCPropertyImplDecl * FindPropertyImplDecl(IdentifierInfo *propertyId, ObjCPropertyQueryKind queryKind) const
FindPropertyImplDecl - This method looks up a previous ObjCPropertyImplDecl added to the list of thos...
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
static bool versionsMatch(const VersionTuple &X, const VersionTuple &Y)
Check whether the two versions match.
static void rewriteToObjCProperty(const ObjCMethodDecl *Getter, const ObjCMethodDecl *Setter, const NSAPI &NS, edit::Commit &commit, unsigned LengthOfPrefix, bool Atomic, bool UseNsIosOnlyMacro, bool AvailabilityArgsMatch)
RetEffect getReturnValue() const
Returns the effect on the return value.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
SourceLocation getBeginLoc() const LLVM_READONLY
DiagnosticsEngine & getDiagnostics() const
Get the current diagnostics engine.
QualType getIntegerType() const
Return the integer type this enum decl corresponds to.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
bool insertBefore(SourceLocation loc, StringRef text)
static Decl::Kind getKind(const Decl *D)
The top declaration context.
Enable migration to NS_ENUM/NS_OPTIONS macros.
bool isPointerType() const
A trivial tuple used to represent a source range.
ObjCMethodDecl * getMethod(Selector Sel, bool isInstance, bool AllowHidden=false) const
An ArgEffect summarizes the retain count behavior on an argument or receiver to a function or method...
ObjCMethodDecl * getInstanceMethod(Selector Sel, bool AllowHidden=false) const
bool isPropertyAccessor() const
bool isFunctionPointerType() const
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
SourceLocation getBegin() const
const LangOptions & getLangOpts() const
ObjCCategoryImplDecl - An object of this class encapsulates a category @implementation declaration...
void addPPCallbacks(std::unique_ptr< PPCallbacks > C)
This class handles loading and caching of source files into memory.
Attr - This represents one attribute.
SourceLocation getLocation() const
QualType getType() const
Return the type wrapped by this type source info.
std::pair< FileID, unsigned > getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
decl_iterator decls_end() const
Qualifiers::ObjCLifetime getObjCLifetime() const
Returns lifetime attribute of this type.
RetEffect summarizes a call's retain/release behavior with respect to its return value.