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;
39 using namespace ento::objc_retain;
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);
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 =
264 ReceiverIsSuper ? Msg->
getSuperLoc() : receiver->getLocEnd();
268 std::string PropertyDotString;
273 PropertyDotString =
").";
276 PropertyDotString =
".";
277 PropertyDotString += Prop->
getName();
278 commit.
replace(SpaceRange, PropertyDotString);
285 commit.
insertWrap(
"(", receiver->getSourceRange(),
")");
286 std::string PropertyDotString =
".";
287 PropertyDotString += Prop->
getName();
288 PropertyDotString +=
" =";
289 const Expr*
const* Args = Msg->
getArgs();
290 const Expr *RHS = Args[0];
294 ReceiverIsSuper ? Msg->
getSuperLoc() : receiver->getLocEnd();
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) {
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);
588 if (!(ASTMigrateActions & FrontendOptions::ObjCMT_ReturnsInnerPointerProperty))
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,
900 EnumDcl->isDeprecated())
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)
920 if (TypedefDcl->isDeprecated())
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);
1087 bool IsUnavailable1 = AA1->getUnavailable();
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) {
1129 if (!Decl1->hasAttrs() || !Decl2->hasAttrs()) {
1130 AvailabilityArgsMatch = (Decl1->hasAttrs() == Decl2->hasAttrs());
1133 AvailabilityArgsMatch =
true;
1134 const AttrVec &Attrs1 = Decl1->getAttrs();
1135 const AttrVec &Attrs2 = Decl2->getAttrs();
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 &
1237 FrontendOptions::ObjCMT_AtomicProperty) != 0,
1238 (ASTMigrateActions &
1241 Editor->commit(commit);
1247 void ObjCMigrateASTConsumer::migrateNsReturnsInnerPointer(
ASTContext &Ctx,
1249 if (OM->isImplicit() ||
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"))
1272 commit.
insertBefore(P->getLocEnd(),
" NS_RETURNS_INNER_POINTER ");
1273 Editor->commit(commit);
1276 void ObjCMigrateASTConsumer::migrateAllMethodInstaceType(
ASTContext &Ctx,
1282 for (
auto *Method : CDecl->
methods()) {
1283 if (Method->isDeprecated())
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";
1398 commit.
insertBefore(FirstFD->getLocStart(), PragmaString);
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) {
1419 if (Decl->isDeprecated())
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);
1434 if (FileId.isInvalid())
1437 else if (AuditKind == CF_BRIDGING_MAY_INCLUDE) {
1438 if (!CFFunctionIBCandidates.empty()) {
1439 CFFunctionIBCandidates.push_back(Decl);
1440 if (FileId.isInvalid())
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) {
1485 if (AE ==
DecRef && !pd->hasAttr<CFConsumedAttr>() &&
1486 NSAPIObj->isMacroDefined(
"CF_CONSUMED")) {
1488 commit.
insertBefore(pd->getLocation(),
"CF_CONSUMED ");
1489 Editor->commit(commit);
1491 else if (AE ==
DecRefMsg && !pd->hasAttr<NSConsumedAttr>() &&
1492 NSAPIObj->isMacroDefined(
"NS_CONSUMED")) {
1494 commit.
insertBefore(pd->getLocation(),
"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) {
1538 if (AE ==
DecRef && !pd->hasAttr<CFConsumedAttr>())
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) {
1611 if (AE ==
DecRef && !pd->hasAttr<CFConsumedAttr>() &&
1612 NSAPIObj->isMacroDefined(
"CF_CONSUMED")) {
1614 commit.
insertBefore(pd->getLocation(),
"CF_CONSUMED ");
1615 Editor->commit(commit);
1620 void ObjCMigrateASTConsumer::migrateAddMethodAnnotation(
1623 if (MethodDecl->
hasBody() || MethodDecl->isImplicit())
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) {
1667 if ((AE ==
DecRef && !pd->hasAttr<CFConsumedAttr>()) || AE ==
IncRef ||
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) { }
1755 Rewrite.ReplaceText(range.
getBegin(), Rewrite.getRangeSize(range),
text);
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) {
1786 std::tie(FID, Offset) = SourceMgr.getDecomposedLoc(Loc);
1789 StringRef(SourceMgr.getFileEntryForID(FID)->getName());
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 =
1799 SourceMgr.getDecomposedLoc(Range.
getBegin());
1800 std::pair<FileID, unsigned>
End =
1801 SourceMgr.getDecomposedLoc(Range.
getEnd());
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) {
1846 if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation)
1847 AnnotateImplicitBridging(Ctx);
1851 if (canModify(CDecl))
1852 migrateObjCContainerDecl(Ctx, CDecl);
1854 if (canModify(CatDecl))
1855 migrateObjCContainerDecl(Ctx, CatDecl);
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)) {
1883 if (!(ASTMigrateActions & FrontendOptions::ObjCMT_NsMacros))
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)) {
1910 if ((ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) &&
1912 migrateCFAnnotation(Ctx, FD);
1916 bool CanModify = canModify(CDecl);
1920 migrateAllMethodInstaceType(Ctx, CDecl);
1922 if ((ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) &&
1924 migrateARCSafeAnnotation(Ctx, CDecl);
1928 ImplD = dyn_cast<ObjCImplementationDecl>(*D)) {
1931 inferDesignatedInitializers(Ctx, ImplD);
1934 if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation)
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()));
1970 FileMgr.FixupRelativePath(filePath);
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;
2012 ObjCMTOpts &= ~(FrontendOptions::ObjCMT_AtomicProperty |
2021 std::vector<std::string> WhiteList =
2023 return llvm::make_unique<ObjCMigrateASTConsumer>(
2036 EditEntry() : File(), Offset(), RemoveLen() {}
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) { }
2077 using namespace llvm::yaml;
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);
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,
2111 using namespace llvm::yaml;
2113 bool Ignore =
false;
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") {
2130 const FileEntry *FE = FileMgr.getFile(Val);
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);
2161 using namespace llvm::sys;
2168 I = Edits.begin(), E = Edits.end();
I !=
E; ++
I) {
2169 const EditEntry &Entry = *
I;
2170 assert(Entry.File == FE);
2174 if (Entry.RemoveLen != 0) {
2181 commit.
insert(Loc, Entry.Text);
2182 }
else if (Entry.Text.empty()) {
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;
2248 Insert = EntriesSet.insert(Entry);
2252 FileEditEntries[Entry.File].push_back(Entry);
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.
The receiver is the instance of the superclass object.
SourceManager & getSourceManager() const
param_const_iterator param_begin() const
bool BeginInvocation(CompilerInstance &CI) override
Callback before starting processing a single input, giving the opportunity to modify the CompilerInvo...
Defines the clang::ASTContext interface.
SourceLocation getEnd() const
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.
FunctionDecl - An instance of this class is created to represent 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.
StringRef getName() const
getName - Get the name of identifier for this declaration as a StringRef.
std::string ObjCMTWhiteListPath
Smart pointer class that efficiently represents Objective-C method names.
SelectorTable & getSelectorTable()
PointerType - C99 6.7.5.1 - Pointer Declarators.
A (possibly-)qualified type.
SourceLocation getBegin() const
Represents a version number in the form major[.minor[.subminor[.build]]].
bool rewriteToObjCSubscriptSyntax(const ObjCMessageExpr *Msg, const NSAPI &NS, Commit &commit)
Implements support for file system lookup, file system caching, and directory search management...
ObjCMethodFamily getMethodFamily() const
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)
IdentifierInfo * getIdentifier() const
getIdentifier - Get the identifier that names this declaration, if there is one.
protocol_loc_iterator protocol_loc_end() const
QualType getQualifiedType(SplitQualType split) const
Un-split a SplitQualType.
bool insertWrap(StringRef before, CharSourceRange range, StringRef after)
static LLVM_READONLY bool isUppercase(unsigned char c)
Return true if this character is an uppercase ASCII letter: [A-Z].
TypedefDecl - Represents the declaration of a typedef-name via the 'typedef' type specifier...
const RewriteBuffer * getRewriteBufferFor(FileID FID) const
getRewriteBufferFor - Return the rewrite buffer for the specified FileID.
const char * getCharacterData(SourceLocation SL, bool *Invalid=nullptr) const
Return a pointer to the start of the specified location in the appropriate spelling MemoryBuffer...
The argument has its reference count decreased by 1.
std::string getAsString() const
static bool TypeIsInnerPointer(QualType T)
IdentifierInfo * getAsIdentifierInfo() const
getAsIdentifierInfo - Retrieve the IdentifierInfo * stored in this declaration name, or NULL if this declaration name isn't a simple identifier.
ObjCProtocolDecl * lookupNestedProtocol(IdentifierInfo *Name)
SourceLocation getDeclaratorEndLoc() const
Returns the location where the declarator ends.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
bool insertAfterToken(SourceLocation loc, StringRef text, bool beforePreviousInsertions=false)
Enable migration of ObjC methods to 'instancetype'.
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)
bool isBlockPointerType() const
const ObjCPropertyDecl * findPropertyDecl(bool CheckOverrides=true) const
Returns the property associated with this method's selector.
ObjCMethodDecl * getMethod(Selector Sel, bool isInstance, bool AllowHidden=false) const
void removeObjCLifetime()
SourceLocation findSemiAfterLocation(SourceLocation loc, ASTContext &Ctx, bool IsDecl=false)
'Loc' is the end of a statement range.
SourceManager & getSourceManager() const
Return the current source manager.
static std::vector< std::string > getWhiteListFilenames(StringRef DirPath)
bool getRawToken(SourceLocation Loc, Token &Result, bool IgnoreWhiteSpace=false)
Relex the token at the specified location.
SourceLocation getLocStart() const LLVM_READONLY
void applyRewrites(EditsReceiver &receiver)
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. ...
decl_iterator decls_end() const
unsigned param_size() const
ParmVarDecl - Represents a parameter to a function.
bool isObjCRetainableType() const
The collection of all-type qualifiers we support.
static EditEntry getTombstoneKey()
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.
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body (definition).
ObjCProtocolDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this Objective-C protocol.
One of these records is kept for each identifier that is lexed.
SourceLocation getSelectorStartLoc() const
static ObjCInstanceTypeFamily getInstTypeMethodFamily(Selector sel)
class LLVM_ALIGNAS(8) DependentTemplateSpecializationType const IdentifierInfo * Name
Represents a template specialization type whose template cannot be resolved, e.g. ...
static std::string applyEditsToTemp(const FileEntry *FE, ArrayRef< EditEntry > Edits, FileManager &FileMgr, DiagnosticsEngine &Diag)
IdentifierInfo * getIdentifierInfoForSlot(unsigned argIndex) const
Retrieve the identifier at a given position in the selector.
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.
ObjCMethodFamily
A family of Objective-C methods.
QualType getReturnType() const
bool isCompleteDefinition() const
isCompleteDefinition - Return true if this decl has its body fully specified.
bool isAnyPointerType() const
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override
Create the AST consumer object for this action, if supported.
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
Token - This structure provides full information about a lexed token.
method_range methods() const
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...
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
Enable migration to add conforming protocols.
unsigned SuppressStrongLifetime
When true, suppress printing of the __strong lifetime qualifier in ARC.
SourceLocation getSuperLoc() const
Retrieve the location of the 'super' keyword for a class or instance message to 'super', otherwise an invalid source location.
static void ReplaceWithInstancetype(ASTContext &Ctx, const ObjCMigrateASTConsumer &ASTC, ObjCMethodDecl *OM)
SourceLocation getBeginLoc() const
Get the begin source location.
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)
SourceLocation getLocWithOffset(int Offset) const
Return a source location with the specified offset from this SourceLocation.
ObjCContainerDecl - Represents a container for method declarations.
const LangOptions & getLangOpts() const
FrontendOptions & getFrontendOpts()
SourceLocation getSuperClassLoc() const
Retrieve the starting location of the superclass.
Enable annotation of ObjCMethods of all kinds.
static bool UseNSOptionsMacro(Preprocessor &PP, ASTContext &Ctx, const EnumDecl *EnumDcl)
The argument has its reference count increased by 1.
ObjCMethodFamily getMethodFamily() const
Determines the family of this method.
static bool rewriteToNSEnumDecl(const EnumDecl *EnumDcl, const TypedefDecl *TypedefDcl, const NSAPI &NS, edit::Commit &commit, StringRef NSIntegerName, bool NSOptions)
tok::TokenKind getTokenID() const
If this is a source-language token (e.g.
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...
bool hasDesignatedInitializers() const
Returns true if this interface decl contains at least one initializer marked with the 'objc_designate...
A builtin binary operation expression such as "x + y" or "x <= y".
RecordDecl * getDecl() const
std::string getNameAsString() const
getNameAsString - Get a human-readable name for the declaration, even if it is one of the special kin...
Expr * IgnoreParenCasts() LLVM_READONLY
IgnoreParenCasts - Ignore parentheses and casts.
ObjCProtocolDecl * getDefinition()
Retrieve the definition of this protocol, if any.
static bool reportDiag(const Twine &Err, DiagnosticsEngine &Diag)
Represents an Objective-C protocol declaration.
SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)
Returns the results of matching Matcher on Node.
A class that does preordor or postorder depth-first traversal on the entire Clang AST and visits each...
Represents an ObjC class declaration.
SourceLocation getLocEnd() const LLVM_READONLY
static EditEntry getEmptyKey()
decl_iterator decls_begin() const
detail::InMemoryDirectory::const_iterator I
Preprocessor & getPreprocessor() const
Return the current preprocessor.
param_iterator param_begin()
DiagnosticsEngine & getDiagnostics() const
ArrayRef< ParmVarDecl * >::const_iterator param_const_iterator
ArgEffect
An ArgEffect summarizes the retain count behavior on an argument or receiver to a function or method...
const ParmVarDecl *const * param_const_iterator
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
SourceLocation getLocStart() const LLVM_READONLY
ObjCProtocolDecl * lookupProtocolNamed(IdentifierInfo *PName)
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
Qualifiers::ObjCLifetime getObjCLifetime() const
Returns lifetime attribute of this type.
ObjCPropertyImplDecl * FindPropertyImplDecl(IdentifierInfo *propertyId, ObjCPropertyQueryKind queryKind) const
FindPropertyImplDecl - This method looks up a previous ObjCPropertyImplDecl added to the list of thos...
static bool AuditedType(QualType AT)
AuditedType - This routine audits the type AT and returns false if it is one of known CF object types...
Enable migration to modern ObjC literals.
bool isFunctionPointerType() const
bool ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl, const ObjCMethodDecl *MethodImp)
const ObjCMethodDecl * getMethodDecl() const
Expr - This represents one expression.
StringRef getName() const
Return the actual identifier string.
Represents a character-granular source range.
SourceLocation getEnd() const
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...
TranslationUnitDecl * getTranslationUnitDecl() const
Defines the clang::Preprocessor interface.
static bool IsCategoryNameWithDeprecatedSuffix(ObjCContainerDecl *D)
Expr ** getArgs()
Retrieve the arguments to this message, not including the receiver.
ObjCInstanceTypeFamily
A family of Objective-C methods.
bool isObjCIdType() const
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file. ...
bool isInstanceMethod() 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)
Enable migration to modern ObjC readwrite property.
DeclarationName getDeclName() const
getDeclName - Get the actual, stored name of the declaration, which may be a special name...
DiagnosticsEngine & getDiagnostics() const
Get the current diagnostics engine.
void CollectInheritedProtocols(const Decl *CDecl, llvm::SmallPtrSet< ObjCProtocolDecl *, 8 > &Protocols)
CollectInheritedProtocols - Collect all protocols in current class and those inherited by it...
const clang::PrintingPolicy & getPrintingPolicy() const
TypeSourceInfo * getReturnTypeSourceInfo() const
bool isMacroDefined(StringRef Id) const
Returns true if Id is currently defined as a macro.
bool hasObjCLifetime() const
static CharSourceRange getCharRange(SourceRange R)
param_const_iterator param_end() const
SourceLocation getEndLoc() const
Get the end source location.
const char * getLiteralData() const
getLiteralData - For a literal token (numeric constant, string, etc), this returns a pointer to the s...
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.
Enable inferring NS_DESIGNATED_INITIALIZER for ObjC methods.
Assigning into this object requires the old value to be released and the new value to be retained...
static void append_attr(std::string &PropertyString, const char *attr, bool &LParenAdded)
const char * getName() const
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
Encodes a location in the source.
enumerator_range enumerators() const
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
unsigned getNumParams() const
getNumParams - Return the number of parameters this function must have based on its FunctionType...
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of enums...
const TemplateArgument * iterator
static unsigned getHashValue(const EditEntry &Val)
SourceRange getBraceRange() const
bool isValid() const
Return true if this is a valid SourceLocation object.
Options for controlling the compiler diagnostics engine.
static void MigrateBlockOrFunctionPointerTypeVariable(std::string &PropertyString, const std::string &TypeString, const char *name)
StringRef getNameForSlot(unsigned argIndex) const
Retrieve the name at a given position in the selector.
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). ...
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...
bool isObjCBuiltinType() const
annotate property with NS_RETURNS_INNER_POINTER
Enable migration to modern ObjC readonly property.
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.
const ObjCInterfaceDecl * getClassInterface() const
Enable migration to modern ObjC subscripting.
bool isPropertyAccessor() const
MacroDefinition getMacroDefinitionAtLoc(const IdentifierInfo *II, SourceLocation Loc)
Represents one property declaration in an Objective-C interface.
QualType getReturnType() const
SourceLocation getBegin() const
lookup_result lookup(DeclarationName Name) const
lookup - Find the declarations (if any) with the given Name in this context.
unsigned getCustomDiagID(Level L, const char(&FormatString)[N])
Return an ID for a diagnostic with the specified format string and level.
static StringRef GetUnsignedName(StringRef NSIntegerName)
QualType getType() const
Return the type wrapped by this type source info.
QualType getObjCInstanceType()
Retrieve the Objective-C "instancetype" type, if already known; otherwise, returns a NULL type;...
QualType getPointeeType() const
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...
ASTContext & getASTContext() const
instmeth_range instance_methods() const
ObjCMigrateAction(std::unique_ptr< FrontendAction > WrappedAction, StringRef migrateDir, unsigned migrateAction)
SourceLocation getSelectorLoc(unsigned Index) const
ObjCMethodDecl * getInstanceMethod(Selector Sel, bool AllowHidden=false) const
Enable migration to NS_ENUM/NS_OPTIONS macros.
static void rewriteToNSMacroDecl(ASTContext &Ctx, const EnumDecl *EnumDcl, const TypedefDecl *TypedefDcl, const NSAPI &NS, edit::Commit &commit, bool IsNSIntegerType)
FileManager & getFileManager() const
Return the current file manager to the caller.
Used for handling and querying diagnostic IDs.
Selector getSelector() const
EnumDecl - Represents an enum.
detail::InMemoryDirectory::const_iterator E
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
param_iterator param_end()
A frontend action which simply wraps some other runtime-specified frontend action.
bool isLiteral() const
Return true if this is a "literal", like a numeric constant, string, etc.
Represents a pointer to an Objective C object.
static bool IsVoidStarType(QualType Ty)
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...
raw_ostream & write(raw_ostream &Stream) const
Write to Stream the result of applying all changes to the original buffer.
const T * getAs() const
Member-template getAs<specific type>'.
instprop_range instance_properties() const
QualType getIntegerType() const
getIntegerType - Return the integer type this enum decl corresponds to.
std::map< FileID, RewriteBuffer >::iterator buffer_iterator
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)
const ObjCProtocolList & getReferencedProtocols() const
unsigned getNumArgs() const
Return the number of actual arguments in this message, not counting the receiver. ...
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.
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
Reading or writing from this object requires a barrier call.
bool initFromDisk(StringRef outputDir, DiagnosticsEngine &Diag, bool ignoreIfFilesChanged)
Rewriter - This is the main interface to the rewrite buffers.
Enable converting setter/getter expressions to property-dot syntx.
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
bool isObjCObjectPointerType() const
static LLVM_READONLY char toLowercase(char c)
Converts the given ASCII character to its lowercase equivalent.
bool isImplicit() const
Indicates whether the message send was implicitly generated by the implementation.
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)
ObjCInterfaceDecl * getSuperClass() const
bool insertBefore(SourceLocation loc, StringRef text)
static Decl::Kind getKind(const Decl *D)
TranslationUnitDecl - The top declaration context.
prefer 'atomic' property over 'nonatomic'.
unsigned getLength() const
SourceLocation getLocForStartOfFile(FileID FID) const
Return the source location corresponding to the first byte of the specified file. ...
static 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_].
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.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
TypeSourceInfo * getTypeSourceInfo() const
ReceiverKind getReceiverKind() const
Determine the kind of receiver that this message is being sent to.
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.
static bool rewriteToObjCInterfaceDecl(const ObjCInterfaceDecl *IDecl, llvm::SmallVectorImpl< ObjCProtocolDecl * > &ConformingProtocols, const NSAPI &NS, edit::Commit &commit)
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
bool isPointerType() const