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 StringRef migrateDir,
184 unsigned migrateAction)
186 ObjCMigAction(migrateAction),
188 if (MigrateDir.empty())
192 std::unique_ptr<ASTConsumer>
197 std::vector<std::unique_ptr<ASTConsumer>> Consumers;
199 Consumers.push_back(llvm::make_unique<ObjCMigrateASTConsumer>(
200 MigrateDir, ObjCMigAction, Remapper, CompInst->
getFileManager(), PPRec,
202 return llvm::make_unique<MultiplexConsumer>(std::move(Consumers));
217 if (isa<ArraySubscriptExpr>(Expr) ||
218 isa<CallExpr>(Expr) ||
219 isa<DeclRefExpr>(Expr) ||
220 isa<CXXNamedCastExpr>(Expr) ||
221 isa<CXXConstructExpr>(Expr) ||
222 isa<CXXThisExpr>(Expr) ||
223 isa<CXXTypeidExpr>(Expr) ||
224 isa<CXXUnresolvedConstructExpr>(Expr) ||
225 isa<ObjCMessageExpr>(Expr) ||
226 isa<ObjCPropertyRefExpr>(Expr) ||
227 isa<ObjCProtocolExpr>(Expr) ||
228 isa<MemberExpr>(Expr) ||
229 isa<ObjCIvarRefExpr>(Expr) ||
230 isa<ParenExpr>(FullExpr) ||
231 isa<ParenListExpr>(Expr) ||
232 isa<SizeOfPackExpr>(Expr))
249 if (Receiver->getType()->isObjCBuiltinType())
263 bool ReceiverIsSuper =
273 ReceiverIsSuper ? Msg->
getSuperLoc() : receiver->getLocEnd();
277 std::string PropertyDotString;
282 PropertyDotString =
").";
285 PropertyDotString =
".";
286 PropertyDotString += Prop->
getName();
287 commit.
replace(SpaceRange, PropertyDotString);
294 commit.
insertWrap(
"(", receiver->getSourceRange(),
")");
295 std::string PropertyDotString =
".";
296 PropertyDotString += Prop->
getName();
297 PropertyDotString +=
" =";
298 const Expr*
const* Args = Msg->
getArgs();
299 const Expr *RHS = Args[0];
303 ReceiverIsSuper ? Msg->
getSuperLoc() : receiver->getLocEnd();
309 if (colon && colon[0] ==
':')
310 PropertyDotString +=
" ";
312 commit.
replace(Range, PropertyDotString);
322 ObjCMigrateASTConsumer &Consumer;
326 ObjCMigrator(ObjCMigrateASTConsumer &consumer,
ParentMap &PMap)
327 : Consumer(consumer), PMap(PMap) { }
329 bool shouldVisitTemplateInstantiations()
const {
return false; }
330 bool shouldWalkTypesOfTypeLocs()
const {
return false; }
336 Consumer.Editor->commit(commit);
342 Consumer.Editor->commit(commit);
347 rewriteToPropertyDotSyntax(E, Consumer.PP, *Consumer.NSAPIObj,
349 Consumer.Editor->commit(commit);
359 if (!TraverseStmt(SubStmt))
362 return WalkUpFromObjCMessageExpr(E);
367 ObjCMigrateASTConsumer &Consumer;
368 std::unique_ptr<ParentMap> PMap;
371 BodyMigrator(ObjCMigrateASTConsumer &consumer) : Consumer(consumer) { }
373 bool shouldVisitTemplateInstantiations()
const {
return false; }
374 bool shouldWalkTypesOfTypeLocs()
const {
return false; }
376 bool TraverseStmt(
Stmt *
S) {
378 ObjCMigrator(Consumer, *PMap).TraverseStmt(S);
384 void ObjCMigrateASTConsumer::migrateDecl(
Decl *D) {
387 if (isa<ObjCMethodDecl>(D))
390 BodyMigrator(*this).TraverseDecl(D);
393 static void append_attr(std::string &PropertyString,
const char *attr,
396 PropertyString +=
"(";
400 PropertyString +=
", ";
401 PropertyString += attr;
406 const std::string& TypeString,
408 const char *argPtr = TypeString.c_str();
413 PropertyString += *argPtr;
417 PropertyString += *argPtr;
422 PropertyString += (*argPtr);
424 PropertyString += name;
429 PropertyString += *argPtr;
439 if (RetainableObject &&
457 else if (RetainableObject)
465 unsigned LengthOfPrefix,
466 bool Atomic,
bool UseNsIosOnlyMacro,
467 bool AvailabilityArgsMatch) {
469 bool LParenAdded =
false;
470 std::string PropertyString =
"@property ";
471 if (UseNsIosOnlyMacro && NS.
isMacroDefined(
"NS_NONATOMIC_IOSONLY")) {
472 PropertyString +=
"(NS_NONATOMIC_IOSONLY";
474 }
else if (!Atomic) {
475 PropertyString +=
"(nonatomic";
480 StringRef PropertyName(PropertyNameString);
481 if (LengthOfPrefix > 0) {
483 PropertyString +=
"(getter=";
487 PropertyString +=
", getter=";
488 PropertyString += PropertyNameString;
492 append_attr(PropertyString,
"readonly", LParenAdded);
497 if (PropertyName.equals(
"target") ||
498 (PropertyName.find(
"delegate") != StringRef::npos) ||
499 (PropertyName.find(
"dataSource") != StringRef::npos)) {
502 append_attr(PropertyString,
"assign", LParenAdded);
503 }
else if (!Setter) {
506 append_attr(PropertyString, MemoryManagementAttr, LParenAdded);
511 append_attr(PropertyString, MemoryManagementAttr, LParenAdded);
514 PropertyString +=
')';
516 if (!isa<TypedefType>(RT)) {
525 PropertyString +=
" ";
528 SubPolicy.SuppressLifetimeQualifiers =
true;
529 std::string TypeString = RT.
getAsString(SubPolicy);
530 if (LengthOfPrefix > 0) {
533 StringRef PropertyNameStringRef(PropertyNameString);
534 PropertyNameStringRef = PropertyNameStringRef.drop_front(LengthOfPrefix);
535 PropertyNameString = PropertyNameStringRef;
536 bool NoLowering = (
isUppercase(PropertyNameString[0]) &&
537 PropertyNameString.size() > 1 &&
540 PropertyNameString[0] =
toLowercase(PropertyNameString[0]);
545 PropertyNameString.c_str());
547 char LastChar = TypeString[TypeString.size()-1];
548 PropertyString += TypeString;
550 PropertyString +=
' ';
551 PropertyString += PropertyNameString;
559 EndGetterSelectorLoc),
561 if (Setter && AvailabilityArgsMatch) {
575 StringRef Name = CatDecl->getName();
576 return Name.endswith(
"Deprecated");
581 void ObjCMigrateASTConsumer::migrateObjCContainerDecl(
ASTContext &Ctx,
586 for (
auto *Method : D->
methods()) {
589 bool PropertyInferred = migrateProperty(Ctx, D, Method);
593 if (!PropertyInferred ||
596 migrateNsReturnsInnerPointer(Ctx, Method);
598 if (!(ASTMigrateActions & FrontendOptions::ObjCMT_ReturnsInnerPointerProperty))
604 migratePropertyNsReturnsInnerPointer(Ctx, Prop);
616 bool HasAtleastOneRequiredProperty =
false;
618 for (
const auto *
Property : PDecl->properties()) {
621 HasAtleastOneRequiredProperty =
true;
628 Property->getDeclName().getAsIdentifierInfo()))
631 else if (
ObjCPropertyDecl *ClassProperty = dyn_cast<ObjCPropertyDecl>(R[0])) {
632 if ((ClassProperty->getPropertyAttributes()
633 !=
Property->getPropertyAttributes()) ||
644 bool HasAtleastOneRequiredMethod =
false;
646 if (PDecl->meth_begin() == PDecl->meth_end())
647 return HasAtleastOneRequiredProperty;
648 for (
const auto *MD : PDecl->methods()) {
649 if (MD->isImplicit())
657 HasAtleastOneRequiredMethod =
true;
658 for (
unsigned I = 0, N = R.
size(); I != N; ++I)
668 if (HasAtleastOneRequiredProperty || HasAtleastOneRequiredMethod)
677 std::string ClassString;
681 if (Protocols.
empty()) {
683 for (
unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
684 ClassString += ConformingProtocols[i]->getNameAsString();
692 for (
unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
693 ClassString += ConformingProtocols[i]->getNameAsString();
706 StringRef UnsignedName = llvm::StringSwitch<StringRef>(NSIntegerName)
707 .Case(
"int8_t",
"uint8_t")
708 .Case(
"int16_t",
"uint16_t")
709 .Case(
"int32_t",
"uint32_t")
710 .Case(
"NSInteger",
"NSUInteger")
711 .Case(
"int64_t",
"uint64_t")
712 .Default(NSIntegerName);
719 StringRef NSIntegerName,
721 std::string ClassString;
723 ClassString =
"typedef NS_OPTIONS(";
727 ClassString =
"typedef NS_ENUM(";
728 ClassString += NSIntegerName;
735 commit.
replace(R, ClassString);
773 bool IsNSIntegerType) {
775 assert(!DesignatedEnumType.
isNull()
776 &&
"rewriteToNSMacroDecl - underlying enum type is null");
779 std::string TypeString = DesignatedEnumType.
getAsString(Policy);
780 std::string ClassString = IsNSIntegerType ?
"NS_ENUM(" :
"NS_OPTIONS(";
781 ClassString += TypeString;
794 while (lbrace[count] !=
'{')
802 commit.
replace(R, ClassString);
813 bool PowerOfTwo =
true;
814 bool AllHexdecimalEnumerator =
true;
815 uint64_t MaxPowerOfTwoVal = 0;
817 const Expr *InitExpr = Enumerator->getInitExpr();
820 AllHexdecimalEnumerator =
false;
824 if (
const BinaryOperator *BO = dyn_cast<BinaryOperator>(InitExpr))
825 if (BO->isShiftOp() || BO->isBitwiseOp())
828 uint64_t EnumVal = Enumerator->getInitVal().getZExtValue();
829 if (PowerOfTwo && EnumVal) {
830 if (!llvm::isPowerOf2_64(EnumVal))
832 else if (EnumVal > MaxPowerOfTwoVal)
833 MaxPowerOfTwoVal = EnumVal;
835 if (AllHexdecimalEnumerator && EnumVal) {
836 bool FoundHexdecimalEnumerator =
false;
842 FoundHexdecimalEnumerator =
843 (StringLit[0] ==
'0' && (
toLowercase(StringLit[1]) ==
'x'));
845 if (!FoundHexdecimalEnumerator)
846 AllHexdecimalEnumerator =
false;
849 return AllHexdecimalEnumerator || (PowerOfTwo && (MaxPowerOfTwoVal > 2));
852 void ObjCMigrateASTConsumer::migrateProtocolConformance(
ASTContext &Ctx,
855 if (!IDecl || ObjCProtocolDecls.empty() || IDecl->
isDeprecated())
859 llvm::SmallPtrSet<ObjCProtocolDecl *, 8> ExplicitProtocols;
864 if (!ExplicitProtocols.count(ProtDecl))
865 PotentialImplicitProtocols.push_back(ProtDecl);
867 if (PotentialImplicitProtocols.empty())
874 for (
unsigned i = 0, e = PotentialImplicitProtocols.size(); i != e; i++)
876 PotentialImplicitProtocols[i]))
877 ConformingProtocols.push_back(PotentialImplicitProtocols[i]);
879 if (ConformingProtocols.empty())
885 for (
unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
888 for (
unsigned i1 = 0, e1 = ConformingProtocols.size(); i1 != e1; i1++) {
890 if (PDecl == TargetPDecl)
899 MinimalConformingProtocols.push_back(TargetPDecl);
901 if (MinimalConformingProtocols.empty())
906 Editor->commit(commit);
909 void ObjCMigrateASTConsumer::CacheObjCNSIntegerTypedefed(
913 if (NSAPIObj->isObjCNSIntegerType(qt))
914 NSIntegerTypedefed = TypedefDcl;
915 else if (NSAPIObj->isObjCNSUIntegerType(qt))
916 NSUIntegerTypedefed = TypedefDcl;
919 bool ObjCMigrateASTConsumer::migrateNSEnumDecl(
ASTContext &Ctx,
926 if (NSIntegerTypedefed) {
927 TypedefDcl = NSIntegerTypedefed;
928 NSIntegerTypedefed =
nullptr;
930 else if (NSUIntegerTypedefed) {
931 TypedefDcl = NSUIntegerTypedefed;
932 NSUIntegerTypedefed =
nullptr;
936 FileID FileIdOfTypedefDcl =
940 if (FileIdOfTypedefDcl != FileIdOfEnumDcl)
947 StringRef NSIntegerName = NSAPIObj->GetNSIntegralKind(qt);
949 if (NSIntegerName.empty()) {
952 if (EnumTy->getDecl() == EnumDcl) {
954 if (!InsertFoundation(Ctx, TypedefDcl->
getLocStart()))
958 Editor->commit(commit);
967 if (!InsertFoundation(Ctx, TypedefDcl->
getLocStart()))
971 commit, NSIntegerName, NSOptions);
972 Editor->commit(commit);
977 const ObjCMigrateASTConsumer &ASTC,
983 std::string ClassString;
985 TypeLoc TL = TSInfo->getTypeLoc();
987 ClassString =
"instancetype";
992 ClassString +=
" (instancetype)";
995 commit.
replace(R, ClassString);
996 ASTC.Editor->commit(commit);
1003 std::string ClassString;
1005 TypeLoc TL = TSInfo->getTypeLoc();
1007 ClassString = IDecl->
getName();
1013 ClassString =
"+ (";
1014 ClassString += IDecl->
getName(); ClassString +=
"*)";
1017 commit.
replace(R, ClassString);
1018 ASTC.Editor->commit(commit);
1021 void ObjCMigrateASTConsumer::migrateMethodInstanceType(
ASTContext &Ctx,
1027 std::string ClassName;
1028 switch (OIT_Family) {
1030 migrateFactoryMethod(Ctx, CDecl, OM);
1033 ClassName =
"NSArray";
1036 ClassName =
"NSDictionary";
1055 IDecl = CatDecl->getClassInterface();
1056 else if (
ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(CDecl))
1061 migrateFactoryMethod(Ctx, CDecl, OM);
1078 T = TD->getDecl()->getUnderlyingType();
1083 if (UPointeeT->isRecordType()) {
1102 const AvailabilityAttr *AA1 = dyn_cast<AvailabilityAttr>(At1);
1105 const AvailabilityAttr *AA2 = dyn_cast<AvailabilityAttr>(At2);
1110 bool IsUnavailable1 = AA1->getUnavailable();
1114 bool IsUnavailable2 = AA2->getUnavailable();
1118 IsUnavailable1 == IsUnavailable2);
1123 bool &AvailabilityArgsMatch) {
1125 for (
unsigned i = 0, e = Attrs1.size(); i != e; i++) {
1127 for (
unsigned j = 0, f = Attrs2.size(); j != f; j++) {
1131 if (Attrs1[i]->
getKind() == Attrs2[j]->getKind()) {
1132 if (AvailabilityArgsMatch)
1152 bool &AvailabilityArgsMatch) {
1157 AvailabilityArgsMatch =
true;
1161 if (match && (Attrs2.size() > Attrs1.size()))
1170 std::string NameString = Name;
1176 bool ObjCMigrateASTConsumer::migrateProperty(
ASTContext &Ctx,
1200 unsigned LengthOfPrefix = 0;
1201 if (!SetterMethod) {
1203 StringRef getterNameString = getterName->
getName();
1204 bool IsPrefix = getterNameString.startswith(
"is");
1209 if (IsPrefix || getterNameString.startswith(
"get")) {
1210 LengthOfPrefix = (IsPrefix ? 2 : 3);
1211 const char *CGetterName = getterNameString.data() + LengthOfPrefix;
1216 if (CGetterName[0] &&
isUppercase(CGetterName[0])) {
1217 getterName = &Ctx.
Idents.
get(CGetterName);
1230 bool AvailabilityArgsMatch;
1231 if (SetterMethod->isDeprecated() ||
1236 QualType SRT = SetterMethod->getReturnType();
1239 const ParmVarDecl *argDecl = *SetterMethod->param_begin();
1246 (ASTMigrateActions &
1248 (ASTMigrateActions &
1250 AvailabilityArgsMatch);
1251 Editor->commit(commit);
1260 (ASTMigrateActions &
1261 FrontendOptions::ObjCMT_AtomicProperty) != 0,
1262 (ASTMigrateActions &
1265 Editor->commit(commit);
1271 void ObjCMigrateASTConsumer::migrateNsReturnsInnerPointer(
ASTContext &Ctx,
1275 OM->
hasAttr<ObjCReturnsInnerPointerAttr>())
1280 !NSAPIObj->isMacroDefined(
"NS_RETURNS_INNER_POINTER"))
1285 Editor->commit(commit);
1288 void ObjCMigrateASTConsumer::migratePropertyNsReturnsInnerPointer(
ASTContext &Ctx,
1293 !NSAPIObj->isMacroDefined(
"NS_RETURNS_INNER_POINTER"))
1297 Editor->commit(commit);
1300 void ObjCMigrateASTConsumer::migrateAllMethodInstaceType(
ASTContext &Ctx,
1306 for (
auto *Method : CDecl->
methods()) {
1309 migrateMethodInstanceType(Ctx, CDecl, Method);
1313 void ObjCMigrateASTConsumer::migrateFactoryMethod(
ASTContext &Ctx,
1327 IDecl = CatDecl->getClassInterface();
1328 else if (
ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(CDecl))
1334 std::string StringClassName = IDecl->
getName();
1335 StringRef LoweredClassName(StringClassName);
1336 std::string StringLoweredClassName = LoweredClassName.lower();
1337 LoweredClassName = StringLoweredClassName;
1344 std::string MethodName = MethodIdName->
getName();
1346 StringRef STRefMethodName(MethodName);
1348 if (STRefMethodName.startswith(
"standard"))
1349 len = strlen(
"standard");
1350 else if (STRefMethodName.startswith(
"shared"))
1351 len = strlen(
"shared");
1352 else if (STRefMethodName.startswith(
"default"))
1353 len = strlen(
"default");
1356 MethodName = STRefMethodName.substr(len);
1358 std::string MethodNameSubStr = MethodName.substr(0, 3);
1359 StringRef MethodNamePrefix(MethodNameSubStr);
1360 std::string StringLoweredMethodNamePrefix = MethodNamePrefix.lower();
1361 MethodNamePrefix = StringLoweredMethodNamePrefix;
1362 size_t Ix = LoweredClassName.rfind(MethodNamePrefix);
1363 if (Ix == StringRef::npos)
1365 std::string ClassNamePostfix = LoweredClassName.substr(Ix);
1366 StringRef LoweredMethodName(MethodName);
1367 std::string StringLoweredMethodName = LoweredMethodName.lower();
1368 LoweredMethodName = StringLoweredMethodName;
1369 if (!LoweredMethodName.startswith(ClassNamePostfix))
1382 Ty = TD->getDecl()->getUnderlyingType();
1408 void ObjCMigrateASTConsumer::AnnotateImplicitBridging(
ASTContext &Ctx) {
1409 if (CFFunctionIBCandidates.empty())
1411 if (!NSAPIObj->isMacroDefined(
"CF_IMPLICIT_BRIDGING_ENABLED")) {
1412 CFFunctionIBCandidates.clear();
1417 const Decl *FirstFD = CFFunctionIBCandidates[0];
1418 const Decl *LastFD =
1419 CFFunctionIBCandidates[CFFunctionIBCandidates.size()-1];
1420 const char *PragmaString =
"\nCF_IMPLICIT_BRIDGING_ENABLED\n\n";
1423 PragmaString =
"\n\nCF_IMPLICIT_BRIDGING_DISABLED\n";
1427 if (isa<FunctionDecl>(LastFD)) {
1437 Editor->commit(commit);
1439 CFFunctionIBCandidates.clear();
1442 void ObjCMigrateASTConsumer::migrateCFAnnotation(
ASTContext &Ctx,
const Decl *
Decl) {
1446 if (Decl->
hasAttr<CFAuditedTransferAttr>()) {
1447 assert(CFFunctionIBCandidates.empty() &&
1448 "Cannot have audited functions/methods inside user "
1449 "provided CF_IMPLICIT_BRIDGING_ENABLE");
1454 if (
const FunctionDecl *FuncDecl = dyn_cast<FunctionDecl>(Decl)) {
1455 CF_BRIDGING_KIND AuditKind = migrateAddFunctionAnnotation(Ctx, FuncDecl);
1456 if (AuditKind == CF_BRIDGING_ENABLE) {
1457 CFFunctionIBCandidates.push_back(Decl);
1458 if (FileId.isInvalid())
1461 else if (AuditKind == CF_BRIDGING_MAY_INCLUDE) {
1462 if (!CFFunctionIBCandidates.empty()) {
1463 CFFunctionIBCandidates.push_back(Decl);
1464 if (FileId.isInvalid())
1469 AnnotateImplicitBridging(Ctx);
1472 migrateAddMethodAnnotation(Ctx, cast<ObjCMethodDecl>(Decl));
1473 AnnotateImplicitBridging(Ctx);
1477 void ObjCMigrateASTConsumer::AddCFAnnotations(
ASTContext &Ctx,
1478 const CallEffects &CE,
1480 bool ResultAnnotated) {
1482 if (!ResultAnnotated) {
1483 RetEffect Ret = CE.getReturnValue();
1484 const char *AnnotationString =
nullptr;
1485 if (Ret.getObjKind() == RetEffect::CF) {
1486 if (Ret.isOwned() && NSAPIObj->isMacroDefined(
"CF_RETURNS_RETAINED"))
1487 AnnotationString =
" CF_RETURNS_RETAINED";
1488 else if (Ret.notOwned() &&
1489 NSAPIObj->isMacroDefined(
"CF_RETURNS_NOT_RETAINED"))
1490 AnnotationString =
" CF_RETURNS_NOT_RETAINED";
1493 if (Ret.isOwned() && NSAPIObj->isMacroDefined(
"NS_RETURNS_RETAINED"))
1494 AnnotationString =
" NS_RETURNS_RETAINED";
1497 if (AnnotationString) {
1500 Editor->commit(commit);
1506 pe = FuncDecl->
param_end(); pi != pe; ++pi, ++i) {
1510 NSAPIObj->isMacroDefined(
"CF_CONSUMED")) {
1513 Editor->commit(commit);
1516 NSAPIObj->isMacroDefined(
"NS_CONSUMED")) {
1519 Editor->commit(commit);
1525 ObjCMigrateASTConsumer::CF_BRIDGING_KIND
1526 ObjCMigrateASTConsumer::migrateAddFunctionAnnotation(
1530 return CF_BRIDGING_NONE;
1532 CallEffects CE = CallEffects::getEffect(FuncDecl);
1533 bool FuncIsReturnAnnotated = (FuncDecl->
hasAttr<CFReturnsRetainedAttr>() ||
1534 FuncDecl->
hasAttr<CFReturnsNotRetainedAttr>() ||
1535 FuncDecl->
hasAttr<NSReturnsRetainedAttr>() ||
1536 FuncDecl->
hasAttr<NSReturnsNotRetainedAttr>() ||
1537 FuncDecl->
hasAttr<NSReturnsAutoreleasedAttr>());
1540 if (FuncIsReturnAnnotated && FuncDecl->
getNumParams() == 0)
1541 return CF_BRIDGING_NONE;
1543 bool ReturnCFAudited =
false;
1544 if (!FuncIsReturnAnnotated) {
1545 RetEffect Ret = CE.getReturnValue();
1546 if (Ret.getObjKind() == RetEffect::CF &&
1547 (Ret.isOwned() || Ret.notOwned()))
1548 ReturnCFAudited =
true;
1550 return CF_BRIDGING_NONE;
1557 bool ArgCFAudited =
false;
1559 pe = FuncDecl->
param_end(); pi != pe; ++pi, ++i) {
1564 ArgCFAudited =
true;
1566 ArgCFAudited =
true;
1571 AddCFAnnotations(Ctx, CE, FuncDecl, FuncIsReturnAnnotated);
1572 return CF_BRIDGING_NONE;
1576 if (ReturnCFAudited || ArgCFAudited)
1577 return CF_BRIDGING_ENABLE;
1579 return CF_BRIDGING_MAY_INCLUDE;
1582 void ObjCMigrateASTConsumer::migrateARCSafeAnnotation(
ASTContext &Ctx,
1584 if (!isa<ObjCInterfaceDecl>(CDecl) || CDecl->
isDeprecated())
1588 for (
const auto *Method : CDecl->
methods())
1589 migrateCFAnnotation(Ctx, Method);
1592 void ObjCMigrateASTConsumer::AddCFAnnotations(
ASTContext &Ctx,
1593 const CallEffects &CE,
1595 bool ResultAnnotated) {
1597 if (!ResultAnnotated) {
1598 RetEffect Ret = CE.getReturnValue();
1599 const char *AnnotationString =
nullptr;
1600 if (Ret.getObjKind() == RetEffect::CF) {
1601 if (Ret.isOwned() && NSAPIObj->isMacroDefined(
"CF_RETURNS_RETAINED"))
1602 AnnotationString =
" CF_RETURNS_RETAINED";
1603 else if (Ret.notOwned() &&
1604 NSAPIObj->isMacroDefined(
"CF_RETURNS_NOT_RETAINED"))
1605 AnnotationString =
" CF_RETURNS_NOT_RETAINED";
1618 if (Ret.isOwned() && NSAPIObj->isMacroDefined(
"NS_RETURNS_RETAINED"))
1619 AnnotationString =
" NS_RETURNS_RETAINED";
1624 if (AnnotationString) {
1627 Editor->commit(commit);
1633 pe = MethodDecl->
param_end(); pi != pe; ++pi, ++i) {
1637 NSAPIObj->isMacroDefined(
"CF_CONSUMED")) {
1640 Editor->commit(commit);
1645 void ObjCMigrateASTConsumer::migrateAddMethodAnnotation(
1651 CallEffects CE = CallEffects::getEffect(MethodDecl);
1652 bool MethodIsReturnAnnotated = (MethodDecl->
hasAttr<CFReturnsRetainedAttr>() ||
1653 MethodDecl->
hasAttr<CFReturnsNotRetainedAttr>() ||
1654 MethodDecl->
hasAttr<NSReturnsRetainedAttr>() ||
1655 MethodDecl->
hasAttr<NSReturnsNotRetainedAttr>() ||
1656 MethodDecl->
hasAttr<NSReturnsAutoreleasedAttr>());
1659 !MethodDecl->
hasAttr<NSConsumesSelfAttr>() &&
1662 NSAPIObj->isMacroDefined(
"NS_CONSUMES_SELF")) {
1665 Editor->commit(commit);
1669 if (MethodIsReturnAnnotated &&
1673 if (!MethodIsReturnAnnotated) {
1674 RetEffect Ret = CE.getReturnValue();
1675 if ((Ret.getObjKind() == RetEffect::CF ||
1677 (Ret.isOwned() || Ret.notOwned())) {
1678 AddCFAnnotations(Ctx, CE, MethodDecl,
false);
1689 pe = MethodDecl->
param_end(); pi != pe; ++pi, ++i) {
1694 AddCFAnnotations(Ctx, CE, MethodDecl, MethodIsReturnAnnotated);
1704 bool shouldVisitTemplateInstantiations()
const {
return false; }
1705 bool shouldWalkTypesOfTypeLocs()
const {
return false; }
1718 return !SuperInitChecker().TraverseStmt(MD->
getBody());
1721 void ObjCMigrateASTConsumer::inferDesignatedInitializers(
1728 if (!NSAPIObj->isMacroDefined(
"NS_DESIGNATED_INITIALIZER"))
1732 if (MD->isDeprecated() ||
1733 MD->getMethodFamily() !=
OMF_init ||
1734 MD->isDesignatedInitializerForTheInterface())
1743 Editor->commit(commit);
1748 bool ObjCMigrateASTConsumer::InsertFoundation(
ASTContext &Ctx,
1750 if (FoundationIncluded)
1756 commit.
insert(Loc,
"#ifndef NS_ENUM\n@import Foundation;\n#endif\n");
1758 commit.
insert(Loc,
"#ifndef NS_ENUM\n#import <Foundation/Foundation.h>\n#endif\n");
1759 Editor->commit(commit);
1760 FoundationIncluded =
true;
1770 RewritesReceiver(
Rewriter &Rewrite) : Rewrite(Rewrite) { }
1776 Rewrite.ReplaceText(range.
getBegin(), Rewrite.getRangeSize(range),
text);
1782 llvm::raw_ostream &OS;
1789 ~JSONEditWriter()
override { OS <<
"]\n"; }
1792 struct EntryWriter {
1794 llvm::raw_ostream &OS;
1811 llvm::sys::fs::make_absolute(Path);
1812 OS <<
" \"file\": \"";
1813 OS.write_escaped(Path.str()) <<
"\",\n";
1814 OS <<
" \"offset\": " << Offset <<
",\n";
1819 std::pair<FileID, unsigned> Begin =
1821 std::pair<FileID, unsigned>
End =
1823 assert(Begin.first == End.first);
1824 assert(Begin.second <= End.second);
1825 unsigned Length = End.second - Begin.second;
1827 OS <<
" \"remove\": " << Length <<
",\n";
1830 void writeText(StringRef Text) {
1831 OS <<
" \"text\": \"";
1832 OS.write_escaped(Text) <<
"\",\n";
1838 Writer.writeLoc(Loc);
1839 Writer.writeText(Text);
1845 Writer.writeRemove(Range);
1846 Writer.writeText(Text);
1852 Writer.writeRemove(Range);
1858 void ObjCMigrateASTConsumer::HandleTranslationUnit(
ASTContext &Ctx) {
1866 if (!FileId.isInvalid() && FileId != FID) {
1867 if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation)
1868 AnnotateImplicitBridging(Ctx);
1872 if (canModify(CDecl))
1873 migrateObjCContainerDecl(Ctx, CDecl);
1875 if (canModify(CatDecl))
1876 migrateObjCContainerDecl(Ctx, CatDecl);
1880 if (canModify(PDecl))
1881 migrateObjCContainerDecl(Ctx, PDecl);
1884 dyn_cast<ObjCImplementationDecl>(*D)) {
1887 migrateProtocolConformance(Ctx, ImpDecl);
1889 else if (
const EnumDecl *ED = dyn_cast<EnumDecl>(*D)) {
1897 if (migrateNSEnumDecl(Ctx, ED, TD) && TD)
1901 migrateNSEnumDecl(Ctx, ED,
nullptr);
1903 else if (
const TypedefDecl *TD = dyn_cast<TypedefDecl>(*D)) {
1904 if (!(ASTMigrateActions & FrontendOptions::ObjCMT_NsMacros))
1911 if (
const EnumDecl *ED = dyn_cast<EnumDecl>(*N)) {
1913 if (
const TypedefDecl *TDF = dyn_cast<TypedefDecl>(*N)) {
1915 if (migrateNSEnumDecl(Ctx, ED, TDF)) {
1917 CacheObjCNSIntegerTypedefed(TD);
1921 if (migrateNSEnumDecl(Ctx, ED, TD)) {
1926 CacheObjCNSIntegerTypedefed(TD);
1928 else if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(*D)) {
1929 if ((ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) &&
1931 migrateCFAnnotation(Ctx, FD);
1935 bool CanModify = canModify(CDecl);
1939 migrateAllMethodInstaceType(Ctx, CDecl);
1941 if ((ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) &&
1943 migrateARCSafeAnnotation(Ctx, CDecl);
1947 ImplD = dyn_cast<ObjCImplementationDecl>(*D)) {
1950 inferDesignatedInitializers(Ctx, ImplD);
1953 if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation)
1954 AnnotateImplicitBridging(Ctx);
1959 llvm::raw_fd_ostream OS(MigrateDir, EC, llvm::sys::fs::F_None);
1968 Editor->applyRewrites(Writer);
1973 RewritesReceiver Rec(rewriter);
1974 Editor->applyRewrites(Rec);
1977 I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) {
1983 llvm::raw_svector_ostream vecOS(newText);
1986 std::unique_ptr<llvm::MemoryBuffer> memBuf(
1987 llvm::MemoryBuffer::getMemBufferCopy(
1988 StringRef(newText.data(), newText.size()), file->
getName()));
1990 FileMgr.FixupRelativePath(filePath);
1991 Remapper.remap(filePath.str(), std::move(memBuf));
2007 using namespace llvm::sys::fs;
2008 using namespace llvm::sys::path;
2010 std::vector<std::string> Filenames;
2011 if (DirPath.empty() || !is_directory(DirPath))
2015 directory_iterator DI = directory_iterator(DirPath, EC);
2016 directory_iterator DE;
2017 for (; !EC && DI != DE; DI = DI.increment(EC)) {
2018 if (is_regular_file(DI->path()))
2019 Filenames.push_back(filename(DI->path()));
2025 std::unique_ptr<ASTConsumer>
2030 unsigned ObjCMTOpts = ObjCMTAction;
2032 ObjCMTOpts &= ~(FrontendOptions::ObjCMT_AtomicProperty |
2041 std::vector<std::string> WhiteList =
2043 return llvm::make_unique<ObjCMigrateASTConsumer>(
2056 EditEntry() : File(), Offset(), RemoveLen() {}
2073 llvm::FoldingSetNodeID
ID;
2074 ID.AddPointer(Val.File);
2075 ID.AddInteger(Val.Offset);
2076 ID.AddInteger(Val.RemoveLen);
2077 ID.AddString(Val.Text);
2078 return ID.ComputeHash();
2080 static bool isEqual(
const EditEntry &LHS,
const EditEntry &RHS) {
2081 return LHS.File == RHS.File &&
2082 LHS.Offset == RHS.Offset &&
2083 LHS.RemoveLen == RHS.RemoveLen &&
2084 LHS.Text == RHS.Text;
2090 class RemapFileParser {
2094 RemapFileParser(
FileManager &FileMgr) : FileMgr(FileMgr) { }
2097 using namespace llvm::yaml;
2099 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
2100 llvm::MemoryBuffer::getFile(File);
2105 Stream YAMLStream(FileBufOrErr.get()->getMemBufferRef(),
SM);
2106 document_iterator I = YAMLStream.begin();
2107 if (I == YAMLStream.end())
2109 Node *Root = I->getRoot();
2113 SequenceNode *SeqNode = dyn_cast<SequenceNode>(Root);
2117 for (SequenceNode::iterator
2118 AI = SeqNode->begin(), AE = SeqNode->end(); AI != AE; ++AI) {
2119 MappingNode *MapNode = dyn_cast<MappingNode>(&*AI);
2122 parseEdit(MapNode, Entries);
2129 void parseEdit(llvm::yaml::MappingNode *
Node,
2131 using namespace llvm::yaml;
2133 bool Ignore =
false;
2135 for (MappingNode::iterator
2136 KVI = Node->begin(), KVE = Node->end(); KVI != KVE; ++KVI) {
2137 ScalarNode *KeyString = dyn_cast<ScalarNode>((*KVI).getKey());
2141 StringRef Key = KeyString->getValue(KeyStorage);
2143 ScalarNode *ValueString = dyn_cast<ScalarNode>((*KVI).getValue());
2147 StringRef Val = ValueString->getValue(ValueStorage);
2149 if (Key ==
"file") {
2150 const FileEntry *FE = FileMgr.getFile(Val);
2154 }
else if (Key ==
"offset") {
2155 if (Val.getAsInteger(10, Entry.Offset))
2157 }
else if (Key ==
"remove") {
2158 if (Val.getAsInteger(10, Entry.RemoveLen))
2160 }
else if (Key ==
"text") {
2166 Entries.push_back(Entry);
2181 using namespace llvm::sys;
2188 I = Edits.begin(), E = Edits.end(); I != E; ++I) {
2189 const EditEntry &Entry = *I;
2190 assert(Entry.File == FE);
2194 if (Entry.RemoveLen != 0) {
2201 commit.
insert(Loc, Entry.Text);
2202 }
else if (Entry.Text.empty()) {
2205 commit.
replace(Range, Entry.Text);
2211 RewritesReceiver Rec(rewriter);
2216 llvm::raw_svector_ostream OS(NewText);
2222 if (fs::createTemporaryFile(path::filename(FE->
getName()),
2223 path::extension(FE->
getName()), FD,
2226 return std::string();
2229 llvm::raw_fd_ostream TmpOut(FD,
true);
2230 TmpOut.write(NewText.data(), NewText.size());
2233 return TempPath.str();
2237 std::vector<std::pair<std::string,std::string> > &remap,
2240 bool hasErrorOccurred =
false;
2244 RemapFileParser
Parser(FileMgr);
2249 DiagClient,
false));
2251 typedef llvm::DenseMap<const FileEntry *, std::vector<EditEntry> >
2253 FileEditEntriesTy FileEditEntries;
2258 I = remapFiles.begin(), E = remapFiles.end(); I != E; ++I) {
2260 if (Parser.parse(*I, Entries))
2264 EI = Entries.begin(), EE = Entries.end(); EI != EE; ++EI) {
2265 EditEntry &Entry = *EI;
2268 std::pair<llvm::DenseSet<EditEntry>::iterator,
bool>
2269 Insert = EntriesSet.insert(Entry);
2273 FileEditEntries[Entry.File].push_back(Entry);
2277 for (FileEditEntriesTy::iterator
2278 I = FileEditEntries.begin(), E = FileEditEntries.end(); I != E; ++I) {
2281 if (TempFile.empty()) {
2282 hasErrorOccurred =
true;
2286 remap.emplace_back(I->first->getName(), TempFile);
2289 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)
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.
ObjCMigrateAction(FrontendAction *WrappedAction, StringRef migrateDir, unsigned migrateAction)
StringRef getName() const
std::string ObjCMTWhiteListPath
ParmVarDecl *const * param_const_iterator
Smart pointer class that efficiently represents Objective-C method names.
SelectorTable & getSelectorTable()
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()
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
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].
Abstract base class for actions which can be performed by the frontend.
const RewriteBuffer * getRewriteBufferFor(FileID FID) const
const char * getCharacterData(SourceLocation SL, bool *Invalid=nullptr) const
Return a pointer to the start of the specified location in the appropriate spelling MemoryBuffer...
std::string getAsString() const
static bool TypeIsInnerPointer(QualType T)
IdentifierInfo * getAsIdentifierInfo() const
ObjCProtocolDecl * lookupNestedProtocol(IdentifierInfo *Name)
SourceLocation getDeclaratorEndLoc() const
Returns the location where the declarator ends. It will be the location of ';' for a method declarati...
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.
bool insertFromRange(SourceLocation loc, CharSourceRange range, bool afterToken=false, bool beforePreviousInsertions=false)
TypeSourceInfo * getIntegerTypeSourceInfo() const
Return the type source info for the underlying integer type, if no type source info exists...
bool isBlockPointerType() const
SourceLocation getLocEnd() const LLVM_READONLY
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. This returns the location of the semicolon following the state...
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...
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
static EditEntry getTombstoneKey()
Base wrapper for a particular "section" of type source info.
Expr * IgnoreImpCasts() LLVM_READONLY
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). The function body might be in any of the (re-)d...
ObjCProtocolDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this Objective-C protocol.
SourceLocation getSelectorStartLoc() const
static ObjCInstanceTypeFamily getInstTypeMethodFamily(Selector sel)
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. This is either a single result (with no stable stora...
ObjCMethodFamily
A family of Objective-C methods.
QualType getReturnType() const
bool isCompleteDefinition() const
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.
method_range methods() const
SourceLocation findLocationAfterSemi(SourceLocation loc, ASTContext &Ctx, bool IsDecl=false)
'Loc' is the end of a statement range. This returns the location immediately after the semicolon foll...
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.
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)
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
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
A builtin binary operation expression such as "x + y" or "x <= y".
RecordDecl * getDecl() const
std::string getNameAsString() const
Expr * IgnoreParenCasts() LLVM_READONLY
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 preorder depth-first traversal on the entire Clang AST and visits each node...
Represents an ObjC class declaration.
SourceLocation getLocEnd() const LLVM_READONLY
static EditEntry getEmptyKey()
decl_iterator decls_begin() const
Preprocessor & getPreprocessor() const
Return the current preprocessor.
param_iterator param_begin()
DiagnosticsEngine & getDiagnostics() const
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
getObjCLifetime - Returns lifetime attribute of this type.
static bool AuditedType(QualType AT)
Enable migration to modern ObjC literals.
ID
Defines the set of possible language-specific address spaces.
bool isFunctionPointerType() const
bool ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl, const ObjCMethodDecl *MethodImp)
const ObjCMethodDecl * getMethodDecl() const
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
DiagnosticsEngine & getDiagnostics() const
Get the current diagnostics engine.
void CollectInheritedProtocols(const Decl *CDecl, llvm::SmallPtrSet< ObjCProtocolDecl *, 8 > &Protocols)
SourceLocation getLocEnd() const LLVM_READONLY
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
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override
Create the AST consumer object for this action, if supported.
static void ReplaceWithClasstype(const ObjCMigrateASTConsumer &ASTC, ObjCMethodDecl *OM)
SourceLocation getLocStart() const LLVM_READONLY
There is no lifetime qualification on this type.
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
ObjCPropertyImplDecl * FindPropertyImplDecl(IdentifierInfo *propertyId) const
Enable inferring NS_DESIGNATED_INITIALIZER for ObjC methods.
static void append_attr(std::string &PropertyString, const char *attr, bool &LParenAdded)
const char * getName() const
Encodes a location in the source. The SourceManager can decode this to get at the full include stack...
enumerator_range enumerators() const
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
unsigned getNumParams() const
const Type * getTypePtr() const
static unsigned getHashValue(const EditEntry &Val)
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)
bool isObjCBuiltinType() const
annotate property with NS_RETURNS_INNER_POINTER
Enable migration to modern ObjC readonly property.
ObjCInterfaceDecl * lookupInheritedClass(const IdentifierInfo *ICName)
static bool AvailabilityAttrsMatch(Attr *At1, Attr *At2)
const ObjCInterfaceDecl * getClassInterface() const
Enable migration to modern ObjC subscripting.
bool isPropertyAccessor() const
Represents one property declaration in an Objective-C interface.
QualType getReturnType() const
SourceLocation getBegin() const
lookup_result lookup(DeclarationName Name) const
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.
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
SourceLocation getSelectorLoc(unsigned Index) const
prop_range properties() 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
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.
static bool IsVoidStarType(QualType Ty)
raw_ostream & write(raw_ostream &Stream) const
Write to Stream the result of applying all changes to the original buffer. Note that it isn't safe to...
QualType getIntegerType() const
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.
Reading or writing from this object requires a barrier call.
bool initFromDisk(StringRef outputDir, DiagnosticsEngine &Diag, bool ignoreIfFilesChanged)
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)
bool isImplicit() const
Indicates whether the message send was implicitly generated by the implementation. If false, it was written explicitly in the source code.
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)
use NS_NONATOMIC_IOSONLY for property 'atomic' attribute
A trivial tuple used to represent a source range.
SourceLocation getLocation() const
std::pair< FileID, unsigned > getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
bool isNull() const
isNull - 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.
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)
bool isDeprecated(std::string *Message=nullptr) const
Determine whether this declaration is marked 'deprecated'.
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