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 return !(isa<ArraySubscriptExpr>(Expr) || isa<CallExpr>(Expr) ||
218 isa<DeclRefExpr>(Expr) || isa<CXXNamedCastExpr>(Expr) ||
219 isa<CXXConstructExpr>(Expr) || isa<CXXThisExpr>(Expr) ||
220 isa<CXXTypeidExpr>(Expr) ||
221 isa<CXXUnresolvedConstructExpr>(Expr) ||
222 isa<ObjCMessageExpr>(Expr) || isa<ObjCPropertyRefExpr>(Expr) ||
223 isa<ObjCProtocolExpr>(Expr) || isa<MemberExpr>(Expr) ||
224 isa<ObjCIvarRefExpr>(Expr) || isa<ParenExpr>(FullExpr) ||
225 isa<ParenListExpr>(Expr) || isa<SizeOfPackExpr>(Expr));
239 if (Receiver->getType()->isObjCBuiltinType())
253 bool ReceiverIsSuper =
263 ReceiverIsSuper ? Msg->
getSuperLoc() : receiver->getLocEnd();
267 std::string PropertyDotString;
272 PropertyDotString =
").";
275 PropertyDotString =
".";
276 PropertyDotString += Prop->
getName();
277 commit.
replace(SpaceRange, PropertyDotString);
284 commit.
insertWrap(
"(", receiver->getSourceRange(),
")");
285 std::string PropertyDotString =
".";
286 PropertyDotString += Prop->
getName();
287 PropertyDotString +=
" =";
288 const Expr*
const* Args = Msg->
getArgs();
289 const Expr *RHS = Args[0];
293 ReceiverIsSuper ? Msg->
getSuperLoc() : receiver->getLocEnd();
299 if (colon && colon[0] ==
':')
300 PropertyDotString +=
" ";
302 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()) {
579 bool PropertyInferred = migrateProperty(Ctx, D, Method);
583 if (!PropertyInferred ||
586 migrateNsReturnsInnerPointer(Ctx, Method);
588 if (!(ASTMigrateActions & FrontendOptions::ObjCMT_ReturnsInnerPointerProperty))
594 migratePropertyNsReturnsInnerPointer(Ctx, Prop);
606 bool HasAtleastOneRequiredProperty =
false;
608 for (
const auto *
Property : PDecl->properties()) {
611 HasAtleastOneRequiredProperty =
true;
618 Property->getDeclName().getAsIdentifierInfo()))
621 else if (
ObjCPropertyDecl *ClassProperty = dyn_cast<ObjCPropertyDecl>(R[0])) {
622 if ((ClassProperty->getPropertyAttributes()
623 !=
Property->getPropertyAttributes()) ||
634 bool HasAtleastOneRequiredMethod =
false;
636 if (PDecl->meth_begin() == PDecl->meth_end())
637 return HasAtleastOneRequiredProperty;
638 for (
const auto *MD : PDecl->methods()) {
639 if (MD->isImplicit())
647 HasAtleastOneRequiredMethod =
true;
648 for (
unsigned I = 0, N = R.
size();
I != N; ++
I)
658 return HasAtleastOneRequiredProperty || HasAtleastOneRequiredMethod;
665 std::string ClassString;
669 if (Protocols.
empty()) {
671 for (
unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
672 ClassString += ConformingProtocols[i]->getNameAsString();
680 for (
unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
681 ClassString += ConformingProtocols[i]->getNameAsString();
694 StringRef UnsignedName = llvm::StringSwitch<StringRef>(NSIntegerName)
695 .Case(
"int8_t",
"uint8_t")
696 .Case(
"int16_t",
"uint16_t")
697 .Case(
"int32_t",
"uint32_t")
698 .Case(
"NSInteger",
"NSUInteger")
699 .Case(
"int64_t",
"uint64_t")
700 .Default(NSIntegerName);
707 StringRef NSIntegerName,
709 std::string ClassString;
711 ClassString =
"typedef NS_OPTIONS(";
715 ClassString =
"typedef NS_ENUM(";
716 ClassString += NSIntegerName;
723 commit.
replace(R, ClassString);
727 if (EndOfEnumDclLoc.
isValid()) {
737 if (EndTypedefDclLoc.
isValid()) {
746 if (EndOfEnumDclLoc.
isValid()) {
761 bool IsNSIntegerType) {
763 assert(!DesignatedEnumType.
isNull()
764 &&
"rewriteToNSMacroDecl - underlying enum type is null");
767 std::string TypeString = DesignatedEnumType.
getAsString(Policy);
768 std::string ClassString = IsNSIntegerType ?
"NS_ENUM(" :
"NS_OPTIONS(";
769 ClassString += TypeString;
782 while (lbrace[count] !=
'{')
790 commit.
replace(R, ClassString);
801 bool PowerOfTwo =
true;
802 bool AllHexdecimalEnumerator =
true;
803 uint64_t MaxPowerOfTwoVal = 0;
805 const Expr *InitExpr = Enumerator->getInitExpr();
808 AllHexdecimalEnumerator =
false;
812 if (
const BinaryOperator *BO = dyn_cast<BinaryOperator>(InitExpr))
813 if (BO->isShiftOp() || BO->isBitwiseOp())
816 uint64_t EnumVal = Enumerator->getInitVal().getZExtValue();
817 if (PowerOfTwo && EnumVal) {
818 if (!llvm::isPowerOf2_64(EnumVal))
820 else if (EnumVal > MaxPowerOfTwoVal)
821 MaxPowerOfTwoVal = EnumVal;
823 if (AllHexdecimalEnumerator && EnumVal) {
824 bool FoundHexdecimalEnumerator =
false;
830 FoundHexdecimalEnumerator =
831 (StringLit[0] ==
'0' && (
toLowercase(StringLit[1]) ==
'x'));
833 if (!FoundHexdecimalEnumerator)
834 AllHexdecimalEnumerator =
false;
837 return AllHexdecimalEnumerator || (PowerOfTwo && (MaxPowerOfTwoVal > 2));
840 void ObjCMigrateASTConsumer::migrateProtocolConformance(
ASTContext &Ctx,
843 if (!IDecl || ObjCProtocolDecls.empty() || IDecl->
isDeprecated())
847 llvm::SmallPtrSet<ObjCProtocolDecl *, 8> ExplicitProtocols;
852 if (!ExplicitProtocols.count(ProtDecl))
853 PotentialImplicitProtocols.push_back(ProtDecl);
855 if (PotentialImplicitProtocols.empty())
862 for (
unsigned i = 0, e = PotentialImplicitProtocols.size(); i != e; i++)
864 PotentialImplicitProtocols[i]))
865 ConformingProtocols.push_back(PotentialImplicitProtocols[i]);
867 if (ConformingProtocols.empty())
873 for (
unsigned i = 0, e = ConformingProtocols.size(); i != e; i++) {
876 for (
unsigned i1 = 0, e1 = ConformingProtocols.size(); i1 != e1; i1++) {
878 if (PDecl == TargetPDecl)
887 MinimalConformingProtocols.push_back(TargetPDecl);
889 if (MinimalConformingProtocols.empty())
894 Editor->commit(commit);
897 void ObjCMigrateASTConsumer::CacheObjCNSIntegerTypedefed(
901 if (NSAPIObj->isObjCNSIntegerType(qt))
902 NSIntegerTypedefed = TypedefDcl;
903 else if (NSAPIObj->isObjCNSUIntegerType(qt))
904 NSUIntegerTypedefed = TypedefDcl;
907 bool ObjCMigrateASTConsumer::migrateNSEnumDecl(
ASTContext &Ctx,
914 if (NSIntegerTypedefed) {
915 TypedefDcl = NSIntegerTypedefed;
916 NSIntegerTypedefed =
nullptr;
918 else if (NSUIntegerTypedefed) {
919 TypedefDcl = NSUIntegerTypedefed;
920 NSUIntegerTypedefed =
nullptr;
924 FileID FileIdOfTypedefDcl =
928 if (FileIdOfTypedefDcl != FileIdOfEnumDcl)
935 StringRef NSIntegerName = NSAPIObj->GetNSIntegralKind(qt);
937 if (NSIntegerName.empty()) {
940 if (EnumTy->getDecl() == EnumDcl) {
942 if (!InsertFoundation(Ctx, TypedefDcl->
getLocStart()))
946 Editor->commit(commit);
955 if (!InsertFoundation(Ctx, TypedefDcl->
getLocStart()))
959 commit, NSIntegerName, NSOptions);
960 Editor->commit(commit);
965 const ObjCMigrateASTConsumer &ASTC,
971 std::string ClassString;
973 TypeLoc TL = TSInfo->getTypeLoc();
975 ClassString =
"instancetype";
980 ClassString +=
" (instancetype)";
983 commit.
replace(R, ClassString);
984 ASTC.Editor->commit(commit);
991 std::string ClassString;
993 TypeLoc TL = TSInfo->getTypeLoc();
995 ClassString = IDecl->
getName();
1001 ClassString =
"+ (";
1002 ClassString += IDecl->
getName(); ClassString +=
"*)";
1005 commit.
replace(R, ClassString);
1006 ASTC.Editor->commit(commit);
1009 void ObjCMigrateASTConsumer::migrateMethodInstanceType(
ASTContext &Ctx,
1015 std::string ClassName;
1016 switch (OIT_Family) {
1018 migrateFactoryMethod(Ctx, CDecl, OM);
1021 ClassName =
"NSArray";
1024 ClassName =
"NSDictionary";
1043 IDecl = CatDecl->getClassInterface();
1044 else if (
ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(CDecl))
1049 migrateFactoryMethod(Ctx, CDecl, OM);
1066 T = TD->getDecl()->getUnderlyingType();
1071 if (UPointeeT->isRecordType()) {
1090 const AvailabilityAttr *AA1 = dyn_cast<AvailabilityAttr>(At1);
1093 const AvailabilityAttr *AA2 = dyn_cast<AvailabilityAttr>(At2);
1098 bool IsUnavailable1 = AA1->getUnavailable();
1102 bool IsUnavailable2 = AA2->getUnavailable();
1106 IsUnavailable1 == IsUnavailable2);
1111 bool &AvailabilityArgsMatch) {
1113 for (
unsigned i = 0, e = Attrs1.size(); i != e; i++) {
1115 for (
unsigned j = 0, f = Attrs2.size(); j != f; j++) {
1119 if (Attrs1[i]->
getKind() == Attrs2[j]->getKind()) {
1120 if (AvailabilityArgsMatch)
1140 bool &AvailabilityArgsMatch) {
1145 AvailabilityArgsMatch =
true;
1149 if (match && (Attrs2.size() > Attrs1.size()))
1158 std::string NameString =
Name;
1164 bool ObjCMigrateASTConsumer::migrateProperty(
ASTContext &Ctx,
1188 unsigned LengthOfPrefix = 0;
1189 if (!SetterMethod) {
1191 StringRef getterNameString = getterName->
getName();
1192 bool IsPrefix = getterNameString.startswith(
"is");
1197 if (IsPrefix || getterNameString.startswith(
"get")) {
1198 LengthOfPrefix = (IsPrefix ? 2 : 3);
1199 const char *CGetterName = getterNameString.data() + LengthOfPrefix;
1204 if (CGetterName[0] &&
isUppercase(CGetterName[0])) {
1205 getterName = &Ctx.
Idents.
get(CGetterName);
1218 bool AvailabilityArgsMatch;
1219 if (SetterMethod->isDeprecated() ||
1224 QualType SRT = SetterMethod->getReturnType();
1227 const ParmVarDecl *argDecl = *SetterMethod->param_begin();
1234 (ASTMigrateActions &
1236 (ASTMigrateActions &
1238 AvailabilityArgsMatch);
1239 Editor->commit(commit);
1248 (ASTMigrateActions &
1249 FrontendOptions::ObjCMT_AtomicProperty) != 0,
1250 (ASTMigrateActions &
1253 Editor->commit(commit);
1259 void ObjCMigrateASTConsumer::migrateNsReturnsInnerPointer(
ASTContext &Ctx,
1263 OM->
hasAttr<ObjCReturnsInnerPointerAttr>())
1268 !NSAPIObj->isMacroDefined(
"NS_RETURNS_INNER_POINTER"))
1273 Editor->commit(commit);
1276 void ObjCMigrateASTConsumer::migratePropertyNsReturnsInnerPointer(
ASTContext &Ctx,
1281 !NSAPIObj->isMacroDefined(
"NS_RETURNS_INNER_POINTER"))
1285 Editor->commit(commit);
1288 void ObjCMigrateASTConsumer::migrateAllMethodInstaceType(
ASTContext &Ctx,
1294 for (
auto *Method : CDecl->
methods()) {
1297 migrateMethodInstanceType(Ctx, CDecl, Method);
1301 void ObjCMigrateASTConsumer::migrateFactoryMethod(
ASTContext &Ctx,
1315 IDecl = CatDecl->getClassInterface();
1316 else if (
ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(CDecl))
1322 std::string StringClassName = IDecl->
getName();
1323 StringRef LoweredClassName(StringClassName);
1324 std::string StringLoweredClassName = LoweredClassName.lower();
1325 LoweredClassName = StringLoweredClassName;
1332 std::string MethodName = MethodIdName->
getName();
1334 StringRef STRefMethodName(MethodName);
1336 if (STRefMethodName.startswith(
"standard"))
1337 len = strlen(
"standard");
1338 else if (STRefMethodName.startswith(
"shared"))
1339 len = strlen(
"shared");
1340 else if (STRefMethodName.startswith(
"default"))
1341 len = strlen(
"default");
1344 MethodName = STRefMethodName.substr(len);
1346 std::string MethodNameSubStr = MethodName.substr(0, 3);
1347 StringRef MethodNamePrefix(MethodNameSubStr);
1348 std::string StringLoweredMethodNamePrefix = MethodNamePrefix.lower();
1349 MethodNamePrefix = StringLoweredMethodNamePrefix;
1350 size_t Ix = LoweredClassName.rfind(MethodNamePrefix);
1351 if (Ix == StringRef::npos)
1353 std::string ClassNamePostfix = LoweredClassName.substr(Ix);
1354 StringRef LoweredMethodName(MethodName);
1355 std::string StringLoweredMethodName = LoweredMethodName.lower();
1356 LoweredMethodName = StringLoweredMethodName;
1357 if (!LoweredMethodName.startswith(ClassNamePostfix))
1370 Ty = TD->getDecl()->getUnderlyingType();
1396 void ObjCMigrateASTConsumer::AnnotateImplicitBridging(
ASTContext &Ctx) {
1397 if (CFFunctionIBCandidates.empty())
1399 if (!NSAPIObj->isMacroDefined(
"CF_IMPLICIT_BRIDGING_ENABLED")) {
1400 CFFunctionIBCandidates.clear();
1405 const Decl *FirstFD = CFFunctionIBCandidates[0];
1406 const Decl *LastFD =
1407 CFFunctionIBCandidates[CFFunctionIBCandidates.size()-1];
1408 const char *PragmaString =
"\nCF_IMPLICIT_BRIDGING_ENABLED\n\n";
1411 PragmaString =
"\n\nCF_IMPLICIT_BRIDGING_DISABLED\n";
1415 if (isa<FunctionDecl>(LastFD)) {
1425 Editor->commit(commit);
1427 CFFunctionIBCandidates.clear();
1430 void ObjCMigrateASTConsumer::migrateCFAnnotation(
ASTContext &Ctx,
const Decl *
Decl) {
1434 if (Decl->
hasAttr<CFAuditedTransferAttr>()) {
1435 assert(CFFunctionIBCandidates.empty() &&
1436 "Cannot have audited functions/methods inside user "
1437 "provided CF_IMPLICIT_BRIDGING_ENABLE");
1442 if (
const FunctionDecl *FuncDecl = dyn_cast<FunctionDecl>(Decl)) {
1443 CF_BRIDGING_KIND AuditKind = migrateAddFunctionAnnotation(Ctx, FuncDecl);
1444 if (AuditKind == CF_BRIDGING_ENABLE) {
1445 CFFunctionIBCandidates.push_back(Decl);
1446 if (FileId.isInvalid())
1449 else if (AuditKind == CF_BRIDGING_MAY_INCLUDE) {
1450 if (!CFFunctionIBCandidates.empty()) {
1451 CFFunctionIBCandidates.push_back(Decl);
1452 if (FileId.isInvalid())
1457 AnnotateImplicitBridging(Ctx);
1460 migrateAddMethodAnnotation(Ctx, cast<ObjCMethodDecl>(Decl));
1461 AnnotateImplicitBridging(Ctx);
1465 void ObjCMigrateASTConsumer::AddCFAnnotations(
ASTContext &Ctx,
1466 const CallEffects &CE,
1468 bool ResultAnnotated) {
1470 if (!ResultAnnotated) {
1471 RetEffect Ret = CE.getReturnValue();
1472 const char *AnnotationString =
nullptr;
1473 if (Ret.getObjKind() == RetEffect::CF) {
1474 if (Ret.isOwned() && NSAPIObj->isMacroDefined(
"CF_RETURNS_RETAINED"))
1475 AnnotationString =
" CF_RETURNS_RETAINED";
1476 else if (Ret.notOwned() &&
1477 NSAPIObj->isMacroDefined(
"CF_RETURNS_NOT_RETAINED"))
1478 AnnotationString =
" CF_RETURNS_NOT_RETAINED";
1481 if (Ret.isOwned() && NSAPIObj->isMacroDefined(
"NS_RETURNS_RETAINED"))
1482 AnnotationString =
" NS_RETURNS_RETAINED";
1485 if (AnnotationString) {
1488 Editor->commit(commit);
1494 pe = FuncDecl->
param_end(); pi != pe; ++pi, ++i) {
1498 NSAPIObj->isMacroDefined(
"CF_CONSUMED")) {
1501 Editor->commit(commit);
1504 NSAPIObj->isMacroDefined(
"NS_CONSUMED")) {
1507 Editor->commit(commit);
1513 ObjCMigrateASTConsumer::CF_BRIDGING_KIND
1514 ObjCMigrateASTConsumer::migrateAddFunctionAnnotation(
1518 return CF_BRIDGING_NONE;
1520 CallEffects CE = CallEffects::getEffect(FuncDecl);
1521 bool FuncIsReturnAnnotated = (FuncDecl->
hasAttr<CFReturnsRetainedAttr>() ||
1522 FuncDecl->
hasAttr<CFReturnsNotRetainedAttr>() ||
1523 FuncDecl->
hasAttr<NSReturnsRetainedAttr>() ||
1524 FuncDecl->
hasAttr<NSReturnsNotRetainedAttr>() ||
1525 FuncDecl->
hasAttr<NSReturnsAutoreleasedAttr>());
1528 if (FuncIsReturnAnnotated && FuncDecl->
getNumParams() == 0)
1529 return CF_BRIDGING_NONE;
1531 bool ReturnCFAudited =
false;
1532 if (!FuncIsReturnAnnotated) {
1533 RetEffect Ret = CE.getReturnValue();
1534 if (Ret.getObjKind() == RetEffect::CF &&
1535 (Ret.isOwned() || Ret.notOwned()))
1536 ReturnCFAudited =
true;
1538 return CF_BRIDGING_NONE;
1545 bool ArgCFAudited =
false;
1547 pe = FuncDecl->
param_end(); pi != pe; ++pi, ++i) {
1552 ArgCFAudited =
true;
1554 ArgCFAudited =
true;
1559 AddCFAnnotations(Ctx, CE, FuncDecl, FuncIsReturnAnnotated);
1560 return CF_BRIDGING_NONE;
1564 if (ReturnCFAudited || ArgCFAudited)
1565 return CF_BRIDGING_ENABLE;
1567 return CF_BRIDGING_MAY_INCLUDE;
1570 void ObjCMigrateASTConsumer::migrateARCSafeAnnotation(
ASTContext &Ctx,
1572 if (!isa<ObjCInterfaceDecl>(CDecl) || CDecl->
isDeprecated())
1576 for (
const auto *Method : CDecl->
methods())
1577 migrateCFAnnotation(Ctx, Method);
1580 void ObjCMigrateASTConsumer::AddCFAnnotations(
ASTContext &Ctx,
1581 const CallEffects &CE,
1583 bool ResultAnnotated) {
1585 if (!ResultAnnotated) {
1586 RetEffect Ret = CE.getReturnValue();
1587 const char *AnnotationString =
nullptr;
1588 if (Ret.getObjKind() == RetEffect::CF) {
1589 if (Ret.isOwned() && NSAPIObj->isMacroDefined(
"CF_RETURNS_RETAINED"))
1590 AnnotationString =
" CF_RETURNS_RETAINED";
1591 else if (Ret.notOwned() &&
1592 NSAPIObj->isMacroDefined(
"CF_RETURNS_NOT_RETAINED"))
1593 AnnotationString =
" CF_RETURNS_NOT_RETAINED";
1606 if (Ret.isOwned() && NSAPIObj->isMacroDefined(
"NS_RETURNS_RETAINED"))
1607 AnnotationString =
" NS_RETURNS_RETAINED";
1612 if (AnnotationString) {
1615 Editor->commit(commit);
1621 pe = MethodDecl->
param_end(); pi != pe; ++pi, ++i) {
1625 NSAPIObj->isMacroDefined(
"CF_CONSUMED")) {
1628 Editor->commit(commit);
1633 void ObjCMigrateASTConsumer::migrateAddMethodAnnotation(
1639 CallEffects CE = CallEffects::getEffect(MethodDecl);
1640 bool MethodIsReturnAnnotated = (MethodDecl->
hasAttr<CFReturnsRetainedAttr>() ||
1641 MethodDecl->
hasAttr<CFReturnsNotRetainedAttr>() ||
1642 MethodDecl->
hasAttr<NSReturnsRetainedAttr>() ||
1643 MethodDecl->
hasAttr<NSReturnsNotRetainedAttr>() ||
1644 MethodDecl->
hasAttr<NSReturnsAutoreleasedAttr>());
1647 !MethodDecl->
hasAttr<NSConsumesSelfAttr>() &&
1650 NSAPIObj->isMacroDefined(
"NS_CONSUMES_SELF")) {
1653 Editor->commit(commit);
1657 if (MethodIsReturnAnnotated &&
1661 if (!MethodIsReturnAnnotated) {
1662 RetEffect Ret = CE.getReturnValue();
1663 if ((Ret.getObjKind() == RetEffect::CF ||
1665 (Ret.isOwned() || Ret.notOwned())) {
1666 AddCFAnnotations(Ctx, CE, MethodDecl,
false);
1677 pe = MethodDecl->
param_end(); pi != pe; ++pi, ++i) {
1682 AddCFAnnotations(Ctx, CE, MethodDecl, MethodIsReturnAnnotated);
1692 bool shouldVisitTemplateInstantiations()
const {
return false; }
1693 bool shouldWalkTypesOfTypeLocs()
const {
return false; }
1706 return !SuperInitChecker().TraverseStmt(MD->
getBody());
1709 void ObjCMigrateASTConsumer::inferDesignatedInitializers(
1716 if (!NSAPIObj->isMacroDefined(
"NS_DESIGNATED_INITIALIZER"))
1720 if (MD->isDeprecated() ||
1721 MD->getMethodFamily() !=
OMF_init ||
1722 MD->isDesignatedInitializerForTheInterface())
1731 Editor->commit(commit);
1736 bool ObjCMigrateASTConsumer::InsertFoundation(
ASTContext &Ctx,
1738 if (FoundationIncluded)
1744 commit.
insert(Loc,
"#ifndef NS_ENUM\n@import Foundation;\n#endif\n");
1746 commit.
insert(Loc,
"#ifndef NS_ENUM\n#import <Foundation/Foundation.h>\n#endif\n");
1747 Editor->commit(commit);
1748 FoundationIncluded =
true;
1758 RewritesReceiver(
Rewriter &Rewrite) : Rewrite(Rewrite) { }
1764 Rewrite.ReplaceText(range.
getBegin(), Rewrite.getRangeSize(range),
text);
1770 llvm::raw_ostream &OS;
1777 ~JSONEditWriter()
override { OS <<
"]\n"; }
1780 struct EntryWriter {
1782 llvm::raw_ostream &OS;
1799 llvm::sys::fs::make_absolute(Path);
1800 OS <<
" \"file\": \"";
1801 OS.write_escaped(Path.str()) <<
"\",\n";
1802 OS <<
" \"offset\": " << Offset <<
",\n";
1807 std::pair<FileID, unsigned> Begin =
1809 std::pair<FileID, unsigned>
End =
1811 assert(Begin.first == End.first);
1812 assert(Begin.second <= End.second);
1813 unsigned Length = End.second - Begin.second;
1815 OS <<
" \"remove\": " << Length <<
",\n";
1818 void writeText(StringRef
Text) {
1819 OS <<
" \"text\": \"";
1820 OS.write_escaped(Text) <<
"\",\n";
1826 Writer.writeLoc(Loc);
1827 Writer.writeText(Text);
1833 Writer.writeRemove(Range);
1834 Writer.writeText(Text);
1840 Writer.writeRemove(Range);
1846 void ObjCMigrateASTConsumer::HandleTranslationUnit(
ASTContext &Ctx) {
1854 if (FileId.isValid() && FileId != FID) {
1855 if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation)
1856 AnnotateImplicitBridging(Ctx);
1860 if (canModify(CDecl))
1861 migrateObjCContainerDecl(Ctx, CDecl);
1863 if (canModify(CatDecl))
1864 migrateObjCContainerDecl(Ctx, CatDecl);
1868 if (canModify(PDecl))
1869 migrateObjCContainerDecl(Ctx, PDecl);
1872 dyn_cast<ObjCImplementationDecl>(*D)) {
1875 migrateProtocolConformance(Ctx, ImpDecl);
1877 else if (
const EnumDecl *ED = dyn_cast<EnumDecl>(*D)) {
1885 if (migrateNSEnumDecl(Ctx, ED, TD) && TD)
1889 migrateNSEnumDecl(Ctx, ED,
nullptr);
1891 else if (
const TypedefDecl *TD = dyn_cast<TypedefDecl>(*D)) {
1892 if (!(ASTMigrateActions & FrontendOptions::ObjCMT_NsMacros))
1899 if (
const EnumDecl *ED = dyn_cast<EnumDecl>(*N)) {
1901 if (
const TypedefDecl *TDF = dyn_cast<TypedefDecl>(*N)) {
1903 if (migrateNSEnumDecl(Ctx, ED, TDF)) {
1905 CacheObjCNSIntegerTypedefed(TD);
1909 if (migrateNSEnumDecl(Ctx, ED, TD)) {
1914 CacheObjCNSIntegerTypedefed(TD);
1916 else if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(*D)) {
1917 if ((ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) &&
1919 migrateCFAnnotation(Ctx, FD);
1923 bool CanModify = canModify(CDecl);
1927 migrateAllMethodInstaceType(Ctx, CDecl);
1929 if ((ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) &&
1931 migrateARCSafeAnnotation(Ctx, CDecl);
1935 ImplD = dyn_cast<ObjCImplementationDecl>(*D)) {
1938 inferDesignatedInitializers(Ctx, ImplD);
1941 if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation)
1942 AnnotateImplicitBridging(Ctx);
1947 llvm::raw_fd_ostream OS(MigrateDir, EC, llvm::sys::fs::F_None);
1956 Editor->applyRewrites(Writer);
1961 RewritesReceiver Rec(rewriter);
1962 Editor->applyRewrites(Rec);
1965 I = rewriter.buffer_begin(), E = rewriter.buffer_end();
I !=
E; ++
I) {
1971 llvm::raw_svector_ostream vecOS(newText);
1973 std::unique_ptr<llvm::MemoryBuffer> memBuf(
1974 llvm::MemoryBuffer::getMemBufferCopy(
1975 StringRef(newText.data(), newText.size()), file->
getName()));
1977 FileMgr.FixupRelativePath(filePath);
1978 Remapper.remap(filePath.str(), std::move(memBuf));
1994 using namespace llvm::sys::fs;
1995 using namespace llvm::sys::path;
1997 std::vector<std::string> Filenames;
1998 if (DirPath.empty() || !is_directory(DirPath))
2002 directory_iterator DI = directory_iterator(DirPath, EC);
2003 directory_iterator DE;
2004 for (; !EC && DI != DE; DI = DI.increment(EC)) {
2005 if (is_regular_file(DI->path()))
2006 Filenames.push_back(filename(DI->path()));
2012 std::unique_ptr<ASTConsumer>
2017 unsigned ObjCMTOpts = ObjCMTAction;
2019 ObjCMTOpts &= ~(FrontendOptions::ObjCMT_AtomicProperty |
2028 std::vector<std::string> WhiteList =
2030 return llvm::make_unique<ObjCMigrateASTConsumer>(
2043 EditEntry() : File(), Offset(), RemoveLen() {}
2060 llvm::FoldingSetNodeID
ID;
2061 ID.AddPointer(Val.File);
2062 ID.AddInteger(Val.Offset);
2063 ID.AddInteger(Val.RemoveLen);
2064 ID.AddString(Val.Text);
2065 return ID.ComputeHash();
2067 static bool isEqual(
const EditEntry &LHS,
const EditEntry &RHS) {
2068 return LHS.File == RHS.File &&
2069 LHS.Offset == RHS.Offset &&
2070 LHS.RemoveLen == RHS.RemoveLen &&
2071 LHS.Text == RHS.Text;
2077 class RemapFileParser {
2081 RemapFileParser(
FileManager &FileMgr) : FileMgr(FileMgr) { }
2084 using namespace llvm::yaml;
2086 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
2087 llvm::MemoryBuffer::getFile(File);
2092 Stream YAMLStream(FileBufOrErr.get()->getMemBufferRef(),
SM);
2093 document_iterator
I = YAMLStream.begin();
2094 if (
I == YAMLStream.end())
2096 Node *Root =
I->getRoot();
2100 SequenceNode *SeqNode = dyn_cast<SequenceNode>(Root);
2105 AI = SeqNode->begin(), AE = SeqNode->end(); AI != AE; ++AI) {
2106 MappingNode *MapNode = dyn_cast<MappingNode>(&*AI);
2109 parseEdit(MapNode, Entries);
2116 void parseEdit(llvm::yaml::MappingNode *
Node,
2118 using namespace llvm::yaml;
2120 bool Ignore =
false;
2123 KVI = Node->begin(), KVE = Node->end(); KVI != KVE; ++KVI) {
2124 ScalarNode *KeyString = dyn_cast<ScalarNode>((*KVI).getKey());
2128 StringRef Key = KeyString->getValue(KeyStorage);
2130 ScalarNode *ValueString = dyn_cast<ScalarNode>((*KVI).getValue());
2134 StringRef Val = ValueString->getValue(ValueStorage);
2136 if (Key ==
"file") {
2137 const FileEntry *FE = FileMgr.getFile(Val);
2141 }
else if (Key ==
"offset") {
2142 if (Val.getAsInteger(10, Entry.Offset))
2144 }
else if (Key ==
"remove") {
2145 if (Val.getAsInteger(10, Entry.RemoveLen))
2147 }
else if (Key ==
"text") {
2153 Entries.push_back(Entry);
2168 using namespace llvm::sys;
2175 I = Edits.begin(), E = Edits.end();
I !=
E; ++
I) {
2176 const EditEntry &Entry = *
I;
2177 assert(Entry.File == FE);
2181 if (Entry.RemoveLen != 0) {
2188 commit.
insert(Loc, Entry.Text);
2189 }
else if (Entry.Text.empty()) {
2192 commit.
replace(Range, Entry.Text);
2198 RewritesReceiver Rec(rewriter);
2203 llvm::raw_svector_ostream OS(NewText);
2208 if (fs::createTemporaryFile(path::filename(FE->
getName()),
2209 path::extension(FE->
getName()).drop_front(), FD,
2212 return std::string();
2215 llvm::raw_fd_ostream TmpOut(FD,
true);
2216 TmpOut.write(NewText.data(), NewText.size());
2219 return TempPath.str();
2223 std::vector<std::pair<std::string,std::string> > &remap,
2226 bool hasErrorOccurred =
false;
2230 RemapFileParser
Parser(FileMgr);
2235 DiagClient,
false));
2237 typedef llvm::DenseMap<const FileEntry *, std::vector<EditEntry> >
2239 FileEditEntriesTy FileEditEntries;
2244 I = remapFiles.begin(), E = remapFiles.end();
I !=
E; ++
I) {
2246 if (Parser.parse(*
I, Entries))
2250 EI = Entries.begin(), EE = Entries.end(); EI != EE; ++EI) {
2251 EditEntry &Entry = *EI;
2255 Insert = EntriesSet.insert(Entry);
2259 FileEditEntries[Entry.File].push_back(Entry);
2264 I = FileEditEntries.begin(), E = FileEditEntries.end();
I !=
E; ++
I) {
2267 if (TempFile.empty()) {
2268 hasErrorOccurred =
true;
2272 remap.emplace_back(
I->first->getName(), TempFile);
2275 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.
ObjCMigrateAction(FrontendAction *WrappedAction, StringRef migrateDir, unsigned migrateAction)
StringRef getName() const
getName - Get the name of identifier for this declaration as a StringRef.
std::string ObjCMTWhiteListPath
ParmVarDecl *const * param_const_iterator
Smart pointer class that efficiently represents Objective-C method names.
SelectorTable & getSelectorTable()
PointerType - C99 6.7.5.1 - Pointer Declarators.
Enable migration to add conforming protocols.
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)
Enable inferring NS_DESIGNATED_INITIALIZER for ObjC methods.
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...
Abstract base class for actions which can be performed by the frontend.
Decl - This represents one declaration (or definition), e.g.
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)
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)
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.
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...
Enable migration to NS_ENUM/NS_OPTIONS macros.
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()
Enable annotation of ObjCMethods of all kinds.
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
Enable migration to modern ObjC readwrite property.
SourceLocation findLocationAfterSemi(SourceLocation loc, ASTContext &Ctx, bool IsDecl=false)
'Loc' is the end of a statement range.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
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
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
FrontendOptions & getFrontendOpts()
SourceLocation getSuperClassLoc() const
Retrieve the starting location of the superclass.
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 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
detail::InMemoryDirectory::const_iterator I
Preprocessor & getPreprocessor() const
Return the current preprocessor.
param_iterator param_begin()
DiagnosticsEngine & getDiagnostics() const
ArgEffect
An ArgEffect summarizes the retain count behavior on an argument or receiver to a function or method...
annotate property with NS_RETURNS_INNER_POINTER
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.
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.
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
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)
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...
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
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)
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
FindPropertyImplDecl - This method looks up a previous ObjCPropertyImplDecl added to the list of thos...
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)
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
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
bool isPropertyAccessor() const
Represents one property declaration in an Objective-C interface.
Enable converting setter/getter expressions to property-dot syntx.
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
Enable migration to modern ObjC readonly property.
SourceLocation getSelectorLoc(unsigned Index) const
prop_range properties() const
ObjCMethodDecl * getInstanceMethod(Selector Sel, bool AllowHidden=false) const
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>'.
use NS_NONATOMIC_IOSONLY for property 'atomic' attribute
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.
Enable migration to modern ObjC subscripting.
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.
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
bool isObjCObjectPointerType() const
prefer 'atomic' property over 'nonatomic'.
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)
Enable migration of ObjC methods to 'instancetype'.
ObjCInterfaceDecl * getSuperClass() const
bool insertBefore(SourceLocation loc, StringRef text)
static Decl::Kind getKind(const Decl *D)
TranslationUnitDecl - The top declaration context.
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.
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
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)
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